Reflection ignores inherited methods

Monkey Forums/Monkey Bug Reports/Reflection ignores inherited methods

arpie(Posted 2016) [#1]
Hello,

I would expect the code below to compile but during the 'Semanting' phase of compilation I get the error:
Method Canine.Woof:Void() must be implemented by class Wolf'

Perhaps I have misunderstood something but I am pretty sure this is the reflection module being a bit too superficial? Without reflection, it compiles and runs perfectly.

Strict

#REFLECTION_FILTER="*"  'reflect everything!
Import reflection

Interface ICanine
  Method Howl:Void()
  Method Woof:Void()
End Interface

Class Dog
  Method Woof:Void()
    Print("Woof")
  End Method
End Class

Class Wolf Extends Dog Implements ICanine
  Method Howl:Void()
    Print("Howl")
  End Method
End Class

Function Main:Int()
  Local dog := New Dog()
  dog.Woof()
  Local wolf := New Wolf()
  wolf.Woof()
  wolf.Howl()
  Return 0
End Function



arpie(Posted 2016) [#2]
Just to clarify - I know dogs are canines and can howl. It is a rubbish, contrived example but nevertheless it *should* compile. The issue is that the reflection module seems to ignore inherited methods.


ImmutableOctet(SKNG)(Posted 2016) [#3]
Reflection enables building of every element in your program. Without it enabled, any code you don't use will be ignored. This means not using the interface will result in it not being compiled.

In this case, you're dealing with an interface resolution error. More specifically, one that was discussed here a decent while back. Basically, your interfaces are incorrect, or rather, the compiler doesn't resolve interfaces using class inheritance unless there's also interface inheritance.

Here's a version that builds:


To explain this a bit, the problem was that 'Dog' wasn't implementing the missing methods. In this case, by "implementing", I mean specifically accepting the rules of the interface in its declaration. Without this, what we end up with is a surface-level issue with ''Wolf', where we were required to provide the method in that class.

There's two fixes for this: The first option is to use interface inheritance like the version above. The second option is to create a derived method, then call upward to the parent's implementation, like this:



In this situation, 'ICanine' is the original version you posted, meaning it has both methods. This also means this is the answer if you can't get 'Dog' to implement a parent interface.

To make a long story short, interfaces need to be a well followed pattern to work properly in Monkey. This means you use interface inheritance in these situations. That also means either explicit support from super-classes like 'Dog', or you write a frontend layer that calls from 'Super'.

The first technique being the example I first revised, and the second being the pattern shown in the second example in this post.


arpie(Posted 2016) [#4]
This thread was only my second forum question and both times @ImmutableOctet you have replied in remarkable time with a very clear, extremely useful response. Interface inheritance will do nicely... On reflection, I should have thought of it before posting, but sometimes it is easy to search too hard in the wrong direction and miss the answer that ought to be obvious. Thanks again for the help.