GObject Introspection: class inheritance and symbol conflict/clash

Let’s say that I have two C classes: ParentClass and SubClass, with SubClass inheriting from ParentClass. Both classes have a method called foo().

In C the functions are:

  • parent_class_foo()
  • sub_class_foo()

So in C there is no problem, we can call the function that we want. But with GI bindings, for example in Python, the syntax is: obj.foo(). The question is, which foo() method is called? Can I rely on the chosen behavior currently implemented by GObject Introspection and/or the language bindings, or is it best to consider it an undefined behavior/implementation detail?


In my case SubClass is a gedit class that provides an API for plugins; but it’s possible to break that API, the plugins just need to be ported. ParentClass is part of a library, not yet used by gedit, and it doesn’t make sense for that library to rename foo() just because gedit is going to use it. (Using composition instead of inheritance is not possible).

The solution that I thought: in SubClass (gedit), use the (rename-to SYMBOL) annotation, symbol by symbol and porting the plugins. Then SubClass can inherit from ParentClass and there won’t be any symbol conflicts/clashes, and the Python/Vala plugins will still work fine.

Is there a best-practice to handle those situations? I haven’t found any information on: https://gi.readthedocs.io/en/latest/

I think that even for dynamically typed languages there is a well defined runtime type for each variable, and the function or method matching this runtime type is called. Have not used Ruby for some years now, but in Ruby there is the keyword super to indicate when we want to call the parent method. And GI bindings should support this hehaviour.

The one for SubClass, as the method name resolution starts from the current class and traverses the type’s hierarchy.

Of course, in theory, any language and language binding can choose their own implementation, which is why you should never have this kind of conflict in a well-designed API.

If you do end up with a conflict, generally, you can use the fully-qualified name:

  ParentClass.foo(instance)
  SubClass.foo(instance)

This should work in most languages.

Thanks for your replies. It answers my question. I’ll see how it goes in gedit :wink:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.