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