Interface question

Monkey Forums/Monkey Programming/Interface question

Gerry Quinn(Posted 2012) [#1]
Probably a silly question, and I'm guessing the answer is no - but what I was wordering is: is there any way to say "object of the same type" when defining an interface.

Say for example, I hant an interface called Holder that defines geometric objects with a certain size, but I did not want to worry about comparing the sizes of different kinds of objects. Say Box and Bag both implement the Holder interface which has a BiggerThan() method. Can the interface be written so that the methods I must create are:

Box.BiggerThan( other:Box )
Bag.BiggerThan( other:Bag )

Or do I just have to go with:

Box.BiggerThan( other:Holder )
Bag.BiggerThan( other:Holder )


offtehcuff(Posted 2012) [#2]
In other languages you can do something like this.

interface Holder<T>
    Method BiggerThan(other:T)
end

class Bag implements Holder<Bag>
    Method BiggerThan(other:Bag)
    end
end


I'm not around a monkey compiler atm so I dunno if that's possible, but I would think it should be.


Gerry Quinn(Posted 2012) [#3]
I guess that would be a generic interface, and the Monkey docs indicate that "interfaces cannot be generic". Suggesting that I was correct in guessing it can't be done.

No big deal, I have little use for interfaces anyway but I just thought they might suit a particular program I am coding.


offtehcuff(Posted 2012) [#4]
Well that's disappointing. I find Monkey has a tricky set of language features.


Gerry Quinn(Posted 2012) [#5]
Seems complete enough to me, though I'd like to see a preprocessor. Mojo is a different matter, but with mojo there is the constraint of having to cater for multiple targets, so incompleteness compared to a native library is to be expected.


marksibly(Posted 2012) [#6]
Hi,

The issue with something like 'Interface Comparable<T>' (and partly why I've been holding off on implementing it) is just how useful it will be on its own, and what else may have to be added to make it useful.

If you're planning on using it with 'sortable' objects like maps, it also implies a bunch of extra syntax to specify 'type constraints', eg: 'Class Map<K Implements Comparable<K>,V>'.

But given the way generics now work in Monkey this is kind of redundant, eg: this will compile anyway as long as K has a valid 'Compare' method:

Class Map<K,V>
   Method Compare( lhs:K,rhs:K )
      Return lhs.Compare( rhs )
   End 
End


I know some users will think this is a bit 'loose', but I think it's a simpler/cleaner solution than going down the complex constraints road, which will never really be as flexible anyway. Either way, it'll fail at compile time if K is not 'comparable'.

The reason this isn't used in the current Map is that it falls over when K is a non-object type like Int/Float - but so would a Comparable<T> key.

So generic interfaces aren't IMO that useful when used with generic classes, which leaves...? The holder/bag example above is interesting, but is it that useful? If bag is a concrete, non-generic class, what is the point of holder having a generic interface? And please excuse my relative ignorance of how Java et-al do this stuff - I'm more used to C++ which is definitely looser but also somewhat more straightforward.

The C++ STL also stresses separating comparison function from object much more which I like - having Compare 'inside' the object strikes me as inflexible as it means you're limited to one comparison function per class. The current mechanism of having to extend Map with a comparison function is a pain, but it does at least mean you can have multiple comparison functions per class. With C#/Java's Comparable<T> setup, this seems much harder to do in a flexible way as you have start using different mechanisms. But perhaps it's not that big a deal.

Anyway, this is still up in the air...any contributions welcome!


Gerry Quinn(Posted 2012) [#7]
I invented the Holder example, but the actual situation was that I am writing a puzzle game involving rectangular objects, but I might at some stage make a new version with objects of a more general shape. Most of the geometry code and many fields of the rectangular objects will then become obsolete; only the method names will remain the same.

It occurred to me that it would be most elegant to make the rectangles implement an interface defining these methods. Then classes that use them could switch easily to the more general shapes that implement the same interface.

Now the code for (say) IsTouching(other) should refer to an object of the same kind.

Of course this can be coded in all sorts of ways. One is to have the complex shapes extend the rectangles, but then the objects will have unused fields. One is to have rectangles and complex shapes both inherit from a base class (this is interfaces by the back door). One is to use interfaces anyway and deal with or ignore the non-genericity (for this project I can ignore it anyway as the rectangles probably won't ever exist in the same game with the more complex shapes).

And there is cut/copy/paste into a new project, which in truth would probably be the fastest! I just thought I might use an interface for the fun of it ;-)

Anyway as you can see the lack of generic interfaces isn't something that's ever likely to bother me particularly! I just posted out of curiosity really.


Samah(Posted 2012) [#8]
With C#/Java's Comparable<T> setup, this seems much harder to do in a flexible way as you have start using different mechanisms.

Java also has a Comparator abstract class which allows you to define comparisons outside the object's class. The Diddy collections framework already has IComparable (interface) and IComparator (an abstract class that supports generics). ArrayList will sort based on either of those.


marksibly(Posted 2012) [#9]
Hi,

> Now the code for (say) IsTouching(other) should refer to an object of the same kind.

This sounds a bit like a 'double dispatch' problem...

With normal OO, you only have one 'selector' - ie: the object whose method is being called - but sometimes it's nice to have more, esp. with 'collision' style methods.

Here's one approach to double dispatch:



Perhaps generic interfaces could help here though?


Samah(Posted 2012) [#10]
But does it make sense to have that kind of functionality in the model? The example you've provided would mean that each Geom subclass would need to implement Collide for every other Geom subclass.

What if the collision detection requires more information than the model for each Geom class can provide? There may be something "world-specific" that would affect the collision.


marksibly(Posted 2012) [#11]
Hi,

> The example you've provided would mean that each Geom subclass would need to implement Collide for every other Geom subclass.

That's kind of the point - it's for situations where you want a 2d 'dispatch' table and have to write N x N algorithms anyway.

It's let you do stuff like...

Function Something( g1:Geom,g2:Geom )
   If g1.Collide( g2 ) 'calls correct collide function depending on runtime type of both g1 AND g2
...etc...
End


It may not be right for this situation, but I've found it useful in the past for low level geom lib intersection/collision etc tests, and it seems vaguely relevant.

More info here:

http://en.wikipedia.org/wiki/Double_dispatch


Gerry Quinn(Posted 2012) [#12]
Mark: "Perhaps generic interfaces could help here though?"

I think I have probably hit on a situation where they would be applicable.

Don't interpret this as a request for generic interfaces, though - they look like things that might be nice to have occasionally, but would never really be necessary or important.


marksibly(Posted 2012) [#13]
Hi,

> Don't interpret this as a request for generic interfaces, though

I'm not counting them out at all - it's just I'm worried that they may not be as useful as people think on their own.

If you could post some realistic 'hypothetical' code that shows how you'd use them in practice, it'd be most useful.


wiebow(Posted 2012) [#14]
I've got some Java example code from the Artemis framework I ported to Blitzmax which uses generic interfaces in a clever way. I will look it up and post it here (I'm not on my main machine now)