Jump to page: 1 25  
Page
Thread overview
Abstract functions in child classes
Dec 01, 2011
Adam
Dec 01, 2011
Regan Heath
Dec 01, 2011
Adam
Dec 01, 2011
Adam
Dec 02, 2011
Jacob Carlborg
Dec 01, 2011
Simen Kjærås
Dec 01, 2011
Adam
Dec 01, 2011
Simen Kjærås
Dec 02, 2011
Jacob Carlborg
Dec 02, 2011
mta`chrono
Dec 02, 2011
bearophile
Dec 02, 2011
Adam
Dec 02, 2011
Adam
Dec 02, 2011
Adam
Dec 02, 2011
Adam
Dec 02, 2011
Jonathan M Davis
Dec 02, 2011
Timon Gehr
Dec 02, 2011
Adam
Dec 02, 2011
Timon Gehr
Dec 02, 2011
Timon Gehr
Dec 02, 2011
Adam
Dec 02, 2011
Timon Gehr
Dec 02, 2011
Jonathan M Davis
Dec 02, 2011
Adam
Dec 02, 2011
Andrej Mitrovic
Dec 02, 2011
Adam
Dec 02, 2011
Regan Heath
Dec 02, 2011
Adam
Dec 02, 2011
Regan Heath
Dec 02, 2011
Adam
Dec 05, 2011
Christophe
Dec 02, 2011
Regan Heath
Dec 02, 2011
Adam
Dec 02, 2011
Regan Heath
Dec 02, 2011
Regan Heath
December 01, 2011
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
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
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
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
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
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
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
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
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
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
« First   ‹ Prev
1 2 3 4 5