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:
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?
This still defeats the purpose of having multiple Medoid types,
as each Medoid is still specified with a specific type.
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









Craig Dillabaugh <craig.dillabaugh gmail.com> 