Thread overview | ||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 01, 2011 Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Ok, starting to feel like I'm missing something obvious... The abstract keyword in the language reference states: "Functions declared as abstract can still have function bodies. This is so that even though they must be overridden, they can still provide ‘base class functionality.’" So, "they must be overridden." Does the compiler do *anything* to verify this for a child class? This compiles: import std.stdio; public abstract class Parent { public void hasDefinition() { writeln("I have a definition"); } public abstract void noDefinition(); } public class Child : Parent { public void unRelated() { writeln("Unrelated"); } } void main() { Child child; } However, if I change main() to: void main() { Parent instance = new Child(); } I get "cannot create instance of abstract class Child | function noDefinition is abstract" Why is a reference / use of child in the context of a parent required just to validate that the class is a valid extension of the parent? More to the point, why does the first case even compile? |
December 01, 2011 Re: Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam | On Thu, 01 Dec 2011 17:50:48 -0000, Adam <Adam@anizi.com> wrote: > Ok, starting to feel like I'm missing something obvious... This: void main() { Child child = new Child; } also produces the (expected) error. Basically dmd was letting you get away with the abstract class because you never instantiated it. Child child; is just a reference to a Child class. You could argue the compiler should error in either case, in fact, I would. But perhaps there is a good generic programming reason not to... someone more experienced might be able to shed some light on it. Regan -- Using Opera's revolutionary email client: http://www.opera.com/mail/ |
December 01, 2011 Re: Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | I saw that a few minutes after posting as well, but if the only time it's going to actually check the definition is if I instantiate it, well... that's not so good for me if I'm writing implementations to be used at a later date. Hm. Guess we'll see. :) |
December 01, 2011 Re: Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam | On Thu, 01 Dec 2011 18:50:48 +0100, Adam <Adam@anizi.com> wrote:
> Ok, starting to feel like I'm missing something obvious...
>
> The abstract keyword in the language reference states:
> "Functions declared as abstract can still have function bodies. This
> is so that even though they must be overridden, they can still
> provide �base class functionality.�"
>
> So, "they must be overridden." Does the compiler do *anything* to
> verify this for a child class?
>
> This compiles:
>
> import std.stdio;
>
> public abstract class Parent {
> public void hasDefinition() {
> writeln("I have a definition");
> }
>
> public abstract void noDefinition();
> }
>
> public class Child : Parent {
> public void unRelated() {
> writeln("Unrelated");
> }
> }
>
> void main() {
> Child child;
> }
>
> However, if I change main() to:
>
> void main() {
> Parent instance = new Child();
> }
>
> I get "cannot create instance of abstract class Child | function
> noDefinition is abstract"
>
> Why is a reference / use of child in the context of a parent
> required just to validate that the class is a valid extension of the
> parent? More to the point, why does the first case even compile?
Child is an abstract class because it has abstract methods. One of
these is the original hasDefinition, the other is noDefinition. Child
itself is under no obligation to override them, because there could be
a class GrandChild : Child, which does override them.
Declaring a variable of type Child, where Child is abstract class,
should of course not be an error. That child could be either a Son or
a Daughter (or a transvestite child, I guess, but let's not get too
carried away), both of whom override these abstract methods.
That said, it would be a lot clearer if the language gave an error
when a class with abstract methods is not marked abstract.
|
December 01, 2011 Re: Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | On Thu, 01 Dec 2011 12:58:24 -0500, Regan Heath <regan@netmail.co.nz> wrote:
> On Thu, 01 Dec 2011 17:50:48 -0000, Adam <Adam@anizi.com> wrote:
>> Ok, starting to feel like I'm missing something obvious...
>
> This:
>
> void main() {
> Child child = new Child;
> }
>
> also produces the (expected) error. Basically dmd was letting you get away with the abstract class because you never instantiated it.
>
> Child child;
>
> is just a reference to a Child class.
>
> You could argue the compiler should error in either case, in fact, I would. But perhaps there is a good generic programming reason not to... someone more experienced might be able to shed some light on it.
A Child reference could be for a further derived GrandChild type that does actually implement the required functions. In fact, Child is also abstract, it just isn't required to be marked as such.
All marking a class as abstract does is make it uninstantiable, just like having an abstract method does. However, you can mark a class abstract to prevent it from being instantiated, even when none of its methods are abstract (could be useful in some situations).
However, I have no idea why you'd mark a concrete function as abstract. That seems like a "just because we could" feature.
-Steve
|
December 01, 2011 Re: Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | I can see the case for a grand-child, but if a class does not provide a definition for an abstract member, is that class not, by association, abstract? "Classes become abstract if they are defined within an abstract attribute, or if any of the virtual member functions within it are declared as abstract." I *assume* that by extending Parent, Child inherits the abstract function. If inheriting an abstract member transitively makes Child an abstract, then I find that the abstract keyword at the class level is little more than explicit documentation. |
December 01, 2011 Re: Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | Because the function in this case has no definition in the base abstract class (Parent), but is referenced / called by Parent's members. I did not want Parent to provide a default definition for the function precisely because a large point of the abstract was that method. |
December 01, 2011 Re: Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam | On Thu, 01 Dec 2011 19:19:49 +0100, Adam <Adam@anizi.com> wrote: > I can see the case for a grand-child, but if a class does not provide > a definition for an abstract member, is that class not, by > association, abstract? Of course. That's what I said. Or meant, at any rate. > "Classes become abstract if they are defined within an abstract > attribute, or if any of the virtual member functions within it are > declared as abstract." > > I *assume* that by extending Parent, Child inherits the abstract > function. If inheriting an abstract member transitively makes Child an > abstract, then I find that the abstract keyword at the class level is > little more than explicit documentation. Indeed. But I'm not one to argue that explicit documentation is bad. |
December 02, 2011 Re: Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On 2011-12-01 19:18, Steven Schveighoffer wrote: > On Thu, 01 Dec 2011 12:58:24 -0500, Regan Heath <regan@netmail.co.nz> > wrote: > >> On Thu, 01 Dec 2011 17:50:48 -0000, Adam <Adam@anizi.com> wrote: >>> Ok, starting to feel like I'm missing something obvious... >> >> This: >> >> void main() { >> Child child = new Child; >> } >> >> also produces the (expected) error. Basically dmd was letting you get >> away with the abstract class because you never instantiated it. >> >> Child child; >> >> is just a reference to a Child class. >> >> You could argue the compiler should error in either case, in fact, I >> would. But perhaps there is a good generic programming reason not >> to... someone more experienced might be able to shed some light on it. > > A Child reference could be for a further derived GrandChild type that > does actually implement the required functions. In fact, Child is also > abstract, it just isn't required to be marked as such. > > All marking a class as abstract does is make it uninstantiable, just > like having an abstract method does. However, you can mark a class > abstract to prevent it from being instantiated, even when none of its > methods are abstract (could be useful in some situations). > > However, I have no idea why you'd mark a concrete function as abstract. > That seems like a "just because we could" feature. > > -Steve The method in the super class could provide a partial implementation that sub class can call. But that might be better divided in two methods. -- /Jacob Carlborg |
December 02, 2011 Re: Abstract functions in child classes | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjærås | On 2011-12-01 19:14, Simen Kjærås wrote: > On Thu, 01 Dec 2011 18:50:48 +0100, Adam <Adam@anizi.com> wrote: > >> Ok, starting to feel like I'm missing something obvious... >> >> The abstract keyword in the language reference states: >> "Functions declared as abstract can still have function bodies. This >> is so that even though they must be overridden, they can still >> provide �base class functionality.�" >> >> So, "they must be overridden." Does the compiler do *anything* to >> verify this for a child class? >> >> This compiles: >> >> import std.stdio; >> >> public abstract class Parent { >> public void hasDefinition() { >> writeln("I have a definition"); >> } >> >> public abstract void noDefinition(); >> } >> >> public class Child : Parent { >> public void unRelated() { >> writeln("Unrelated"); >> } >> } >> >> void main() { >> Child child; >> } >> >> However, if I change main() to: >> >> void main() { >> Parent instance = new Child(); >> } >> >> I get "cannot create instance of abstract class Child | function >> noDefinition is abstract" >> >> Why is a reference / use of child in the context of a parent >> required just to validate that the class is a valid extension of the >> parent? More to the point, why does the first case even compile? > > Child is an abstract class because it has abstract methods. One of > these is the original hasDefinition, the other is noDefinition. Child > itself is under no obligation to override them, because there could be > a class GrandChild : Child, which does override them. > > Declaring a variable of type Child, where Child is abstract class, > should of course not be an error. That child could be either a Son or > a Daughter (or a transvestite child, I guess, but let's not get too > carried away), both of whom override these abstract methods. > > That said, it would be a lot clearer if the language gave an error > when a class with abstract methods is not marked abstract. There's also the possibility to have the declarations in one object file and the implementation in another, if I recall correctly. This allows to use a .di and .d file, similar to .c and .h in C/C++. -- /Jacob Carlborg |
Copyright © 1999-2021 by the D Language Foundation