reimplementing an interface in a derived class
Simen Kjærås
simen.kjaras at gmail.com
Fri Jan 4 09:19:48 UTC 2019
On Friday, 4 January 2019 at 08:40:04 UTC, Alex wrote:
> class A
> {
> public:
> int foo(){return 1;}
> };
> class B : public A
> {
> public:
> int foo(){return 2;}
> };
In C++, methods are non-virtual by default. In D, they are
virtual by default. Because of this, the two examples are
different. In fact, D disallows overriding non-virtual,
non-private functions, as specified in
https://dlang.org/spec/function.html#virtual-functions. For
private functions it does work, though:
class A {
private final int foo() { return 1; }
}
class B : A {
final int foo() { return 2; }
}
unittest {
assert((new A).foo == 1);
assert((new B).foo == 2);
assert((cast(A)(new B)).foo == 1);
}
> Now I have the feeling, I'm missing something elementary...
> sorry for this...
> But take the classic example of OOP of an Animal and a Dog:
> Animal.
> Let the animal implement some default move and eat behavior.
> Let the dog override the move method and implement bark.
> If you degrade the dog to the animal by casting it should still
> be able to move and eat, but not bark.
Imagine you give me a box with an Animal in it. You know it's a
Bird, but I only know it's an Animal of some kind.
Case 1: I tell it to move() to the top of a tree. Would you
expect it to climb or fly?
(let's not get into penguins and other flightless birds right
now, the OOP animal metaphor is strained enough as it is)
Case 2: I try to tell it to bark(), but there's no way to do
that, because I have access to it as an Animal, not a Dog.
Cutting off its beak and gluing a muzzle there (casting a Bird to
a Dog) will only lead to suffering.
Case 1 is overriding - Bird has defined how move() should work,
and it will do that even if you only know it's an animal of some
kind. Case 2 is subclassing - a Dog can do things that the
average Animal can't, and this is reflected in it having a wider
interface - more methods.
This can be exemplified in D as:
import std.stdio : writeln;
abstract class Animal {
abstract void move();
}
class Bird : Animal {
override void move() {
writeln("Flying.");
}
}
class Dog : Animal {
override void move() {
writeln("Walking."); // Assume this is not Muttley
}
void bark() {
writeln("Woof!");
}
}
unittest {
(new Bird).move(); // Flying
(cast(Animal)new Bird).move(); // Flying
//(cast(Animal)new Bird).bark(); // Fails to compile -
generic animals can't bark
(cast(Dog)new Bird).bark(); // Crashes because a Bird is not
a Dog, cast returns null.
}
--
Simen
More information about the Digitalmars-d-learn
mailing list