digitalmars.D.learn - Object oriented programming and interfaces
- Dirk (16/16) Dec 04 2017 Hi!
- Craig Dillabaugh (12/28) Dec 04 2017 Interfaces are expected to implement static or final functions.
- Adam D. Ruppe (12/26) Dec 04 2017 So what would happen there if someone did:
- Jacob Carlborg (10/32) Dec 04 2017 I don't think so. In the "Item" class you have declared "distance" to
- A Guy With a Question (4/7) Dec 04 2017 The two signatures need to be the same. I think this is true of
- Dirk (25/25) Dec 04 2017 The distance function is implementation dependend and can only be
- Andrea Fontana (2/3) Dec 05 2017 Did you tried to use introspection?
- Daniel Kozak (19/42) Dec 05 2017 You can do something like this:
- bauss (3/55) Dec 05 2017 This still defeats the purpose of having multiple Medoid types,
- Adam D. Ruppe (31/34) Dec 05 2017 Just don't put it in the interface. Leave it in the individual
- Jesse Phillips (12/28) Dec 05 2017 I think everyone here has missed the reason.
- Steven Schveighoffer (13/35) Dec 05 2017 You are thinking about covariance and contravariance.
Hi! I defined an interface: interface Medoid { float distance( Medoid other ); uint id() const property; } and a class implementing that interface: class Item : Medoid { float distance( Item i ) {...} uint id() const property {...} } The compiler says: Error: class Item interface function 'float distance(Medoid other)' is not implemented Is there a way to implement the Item.distance() member function taking any object whose class is Item?
Dec 04 2017
On Monday, 4 December 2017 at 20:43:27 UTC, Dirk wrote:Hi! I defined an interface: interface Medoid { float distance( Medoid other ); uint id() const property; } and a class implementing that interface: class Item : Medoid { float distance( Item i ) {...} uint id() const property {...} } The compiler says: Error: class Item interface function 'float distance(Medoid other)' is not implemented Is there a way to implement the Item.distance() member function taking any object whose class is Item?Interfaces are expected to implement static or final functions. https://dlang.org/spec/interface.html interface Medoid { static float distance( Medoid other ); uint id() const property; } class Item : Medoid { static float distance( Item i ) { return 0.0f; } uint id() const property { return 1; } }
Dec 04 2017
On Monday, 4 December 2017 at 20:43:27 UTC, Dirk wrote:interface Medoid { float distance( Medoid other ); uint id() const property; } and a class implementing that interface: class Item : Medoid { float distance( Item i ) {...} uint id() const property {...} } The compiler says: Error: class Item interface function 'float distance(Medoid other)' is not implemented Is there a way to implement the Item.distance() member function taking any object whose class is Item?So what would happen there if someone did: Medoid i = new Item(); i.distance(new OtherMedoid()); What does it call there? The OtherMedoid isn't an Item, so your Item.distance method wouldn't work... meaning it didn't actually implement the interface. Item.distance CAN take any Item, that function is legal... it just doesn't impelment the interface since it isn't broad enough to take anything the interface can take. So remove it from the interface or implement a generic version too.
Dec 04 2017
On 2017-12-04 21:43, Dirk wrote:Hi! I defined an interface: interface Medoid { float distance( Medoid other ); uint id() const property; } and a class implementing that interface: class Item : Medoid { float distance( Item i ) {...} uint id() const property {...} } The compiler says: Error: class Item interface function 'float distance(Medoid other)' is not implemented Is there a way to implement the Item.distance() member function taking any object whose class is Item?I don't think so. In the "Item" class you have declared "distance" to take an instance of "Item", which is more specialized than "Medoid". If an instance of "Item" is used through the "Medoid" interface, that interface allows to pass any object to the "distance" method that implements the "Medoid" interface. That can be a different class than "Medoid". You could add an overload that takes an instance of "Item", if that helps. -- /Jacob Carlborg
Dec 04 2017
On Monday, 4 December 2017 at 20:43:27 UTC, Dirk wrote:Hi! float distance( Medoid other );float distance( Item i ) {...}The two signatures need to be the same. I think this is true of most OOP languages. Have them both be: float distance( Medoid other );
Dec 04 2017
The distance function is implementation dependend and can only be computed between two objects of the same class (in this example the class is Item). My goal is to write a module for a k-medoids clustering algorithm. The class MedoidClassification shall be able to partition a list of objects from the same class, which implement the Medoid interface. My current approach is this (which does not work): interface Medoid { float distance( Medoid other ); uint id() const property; } class Item : Medoid { float distance( Item m ) {...} uint id() const property {...} } class MedoidClassification { this( Medoid[] list ) {...} Medoid[][] getClusters() {...} } void main() { Item[10] items; auto mc = MedoidClassification( items ); } What would be a good way to implement this?
Dec 04 2017
On Tuesday, 5 December 2017 at 07:47:32 UTC, Dirk wrote:What would be a good way to implement this?Did you tried to use introspection?
Dec 05 2017
You can do something like this: interface Medoid(T) { float distance( T other ); uint id() const property; } class Item : Medoid!(Item) { float distance( Item m ) { return 0.;} uint id() const property { return 1; } } class MedoidClassification { this(T:Medoid!T)(T[] list) {} //Medoid[][] getClusters() {...} } void main() { auto items = new Item[10]; auto mc = new MedoidClassification( items ); } On Tue, Dec 5, 2017 at 8:47 AM, Dirk via Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:The distance function is implementation dependend and can only be computed between two objects of the same class (in this example the class is Item). My goal is to write a module for a k-medoids clustering algorithm. The class MedoidClassification shall be able to partition a list of objects from the same class, which implement the Medoid interface. My current approach is this (which does not work): interface Medoid { float distance( Medoid other ); uint id() const property; } class Item : Medoid { float distance( Item m ) {...} uint id() const property {...} } class MedoidClassification { this( Medoid[] list ) {...} Medoid[][] getClusters() {...} } void main() { Item[10] items; auto mc = MedoidClassification( items ); } What would be a good way to implement this?
Dec 05 2017
On Tuesday, 5 December 2017 at 08:08:55 UTC, Daniel Kozak wrote:You can do something like this: interface Medoid(T) { float distance( T other ); uint id() const property; } class Item : Medoid!(Item) { float distance( Item m ) { return 0.;} uint id() const property { return 1; } } class MedoidClassification { this(T:Medoid!T)(T[] list) {} //Medoid[][] getClusters() {...} } void main() { auto items = new Item[10]; auto mc = new MedoidClassification( items ); } On Tue, Dec 5, 2017 at 8:47 AM, Dirk via Digitalmars-d-learn < digitalmars-d-learn puremagic.com> wrote:This still defeats the purpose of having multiple Medoid types, as each Medoid is still specified with a specific type.The distance function is implementation dependend and can only be computed between two objects of the same class (in this example the class is Item). My goal is to write a module for a k-medoids clustering algorithm. The class MedoidClassification shall be able to partition a list of objects from the same class, which implement the Medoid interface. My current approach is this (which does not work): interface Medoid { float distance( Medoid other ); uint id() const property; } class Item : Medoid { float distance( Item m ) {...} uint id() const property {...} } class MedoidClassification { this( Medoid[] list ) {...} Medoid[][] getClusters() {...} } void main() { Item[10] items; auto mc = MedoidClassification( items ); } What would be a good way to implement this?
Dec 05 2017
On Tuesday, 5 December 2017 at 07:47:32 UTC, Dirk wrote:The distance function is implementation dependend and can only be computed between two objects of the same class (in this example the class is Item).Just don't put it in the interface. Leave it in the individual classes with the stricter definition. Or, as I said before, implement the interface by asking the question: what if you call Item.distance (NotAnItem)? Maybe you could throw an exception or return NaN to show this is an invalid comparison. But if it is in the interface, you MUST answer that question somehow. --- interface Medoid { float distance(Medoid other); } class Item { float distance(Medoid other) { if(auto item = cast(Item) other) { // it is an item, implement comparison here } else { return float.nan; // invalid comparison } } } --- Tip: you can generically test that two objects are of the same class through their interfaces by checking: if(typeid(cast(Object) o1) == typeid(cast(Object) o2)) { // same class } else { // same interface, but different class } Might be useful for your classifier, though checking the nan of distance might be good too.
Dec 05 2017
On Monday, 4 December 2017 at 20:43:27 UTC, Dirk wrote:Hi! I defined an interface: interface Medoid { float distance( Medoid other ); uint id() const property; } and a class implementing that interface: class Item : Medoid { float distance( Item i ) {...} uint id() const property {...} } The compiler says: Error: class Item interface function 'float distance(Medoid other)' is not implemented Is there a way to implement the Item.distance() member function taking any object whose class is Item?I think everyone here has missed the reason. The problem is that a derived type can do more, the interface only allows for two method calls while the class could theoretically do more. If the compiler allowed the class it would let you access functions and members not available to the interfaces, and the function would still be passed a Medoid. You could make a cast within your function, but then you're still really not handling the interface but that at least would be clear in the code rather than the compiler hiding it by ignoring the problem.
Dec 05 2017
On 12/4/17 3:43 PM, Dirk wrote:Hi! I defined an interface: interface Medoid { float distance( Medoid other ); uint id() const property; } and a class implementing that interface: class Item : Medoid { float distance( Item i ) {...} uint id() const property {...} } The compiler says: Error: class Item interface function 'float distance(Medoid other)' is not implemented Is there a way to implement the Item.distance() member function taking any object whose class is Item?You are thinking about covariance and contravariance. In D, only the return value can work with covariance: interface Medoid { Medoid getIt(); } class Item : Medoid { Item getIt() { return this; } } D does not support contravariance on parameters. And in any case you have it backwards. A derived override could take a base type, but not a more specific type, for the reasons Adam outlined. -Steve
Dec 05 2017