www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - access subclass functions

reply "Saaa" <empty needmail.com> writes:
Is this not possible, or am I doing anything wrong?

Fruit[2] fruits; // Fruit has no peel function

fruit[0]= new Apple();
fruit[1]= new Banana(); //Banana has a protected peel() function returning a 
bool

bool b;
b=fruit[1].peal();

Error: no property 'peel' for type 'project.fruitclass.Fruit'
Error: function expected before (), not 1 of type int
Error: cannot implicitly convert expression (cast(Banana)1()) of type 
'project.banana.Banana' to bool 
Nov 20 2008
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Saaa" wrote
 Is this not possible, or am I doing anything wrong?

 Fruit[2] fruits; // Fruit has no peel function

 fruit[0]= new Apple();
 fruit[1]= new Banana(); //Banana has a protected peel() function returning 
 a bool

 bool b;
 b=fruit[1].peal();

 Error: no property 'peel' for type 'project.fruitclass.Fruit'
 Error: function expected before (), not 1 of type int
 Error: cannot implicitly convert expression (cast(Banana)1()) of type 
 'project.banana.Banana' to bool

I think you have a typo in your example (and your example doesn't reflect the error messages), but that isn't the problem. In a strongly typed language, you cannot access subclass functions that aren't defined in the base class unless you are sure the instance is of the subclass type. to fix, you should do this: if(auto ban = cast(Banana)fruit[1]) ban.peel(); the if(auto ban = ...) ensures that fruit[1] is a Banana. If you are sure it will always be a banana (i.e. the cast doesn't return null), you can do: (cast(Banana)fruit[1]).peel(); -Steve
Nov 20 2008
parent reply "Saaa" <empty needmail.com> writes:
 I think you have a typo in your example

 (and your example doesn't reflect the error messages),

As you noticed it isn't the actual code, but I thought it would reflect it though.
 but that isn't the problem.

 In a strongly typed language, you cannot access subclass functions that 
 aren't defined in the base class unless you are sure the instance is of 
 the subclass type.

 to fix, you should do this:

 if(auto ban = cast(Banana)fruit[1])
  ban.peel();

 the if(auto ban = ...) ensures that fruit[1] is a Banana.  If you are sure 
 it will always be a banana (i.e. the cast doesn't return null), you can 
 do:

 (cast(Banana)fruit[1]).peel();

Now that you mention it, I think I've had this problem before :/ even though it is really logical, thx again. In stead of numbers I use an enum, which makes it really difficult to get this wrong: fruits[BANANA].peel(); :D Now that I got this out of the way I see peel() should be public.
Nov 20 2008
next sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
"Saaa" wrote
 (and your example doesn't reflect the error messages),

As you noticed it isn't the actual code, but I thought it would reflect it though.

I mean, you have some cast error, but there is no casting in your code sample. -Steve
Nov 20 2008
parent reply "Saaa" <empty needmail.com> writes:
My bad, I meant:

b=cast(Banana)fruits[1].peel();


"Steven Schveighoffer" <schveiguy yahoo.com> wrote in message 
news:gg3p0v$2494$1 digitalmars.com...
 "Saaa" wrote
 (and your example doesn't reflect the error messages),

As you noticed it isn't the actual code, but I thought it would reflect it though.

I mean, you have some cast error, but there is no casting in your code sample. -Steve

Nov 20 2008
parent BCS <ao pathlink.com> writes:
Reply to Saaa,

 
 b=cast(Banana)fruits[1].peel();
 

I'm not shure that will work. IIRC DMD reads that as b=cast(Banana)( fruits[1].peel() );
Nov 20 2008
prev sibling parent reply Kagamin <spam here.lot> writes:
Saaa Wrote:

 In stead of numbers I use an enum, which makes it really difficult to get 
 this wrong:
 fruits[BANANA].peel();

why not using struct?
Nov 20 2008
parent reply "Saaa" <empty needmail.com> writes:
"Kagamin" <spam here.lot> wrote in message 
news:gg3t81$2flu$1 digitalmars.com...
 Saaa Wrote:

 In stead of numbers I use an enum, which makes it really difficult to get
 this wrong:
 fruits[BANANA].peel();

why not using struct?

How do you mean? What should be a struct?
Nov 20 2008
parent reply Kagamin <spam here.lot> writes:
Saaa Wrote:

 this wrong:
 fruits[BANANA].peel();

why not using struct?

How do you mean? What should be a struct?

Nov 21 2008
parent "Saaa" <empty needmail.com> writes:
You mean something like this ?

struct fruits
{
    Banana banana();
    Apple apple();
}

I now use foreach(int i, Fruit fruit; fruits) a lot.
How do I iterate over all elements when I use the above?


 Saaa Wrote:

 this wrong:
 fruits[BANANA].peel();

why not using struct?

How do you mean? What should be a struct?


Nov 21 2008
prev sibling parent reply sclytrack <sclytrack pi.be> writes:
== Quote from Saaa (empty needmail.com)'s article
 Is this not possible, or am I doing anything wrong?
 Fruit[2] fruits; // Fruit has no peel function
 fruit[0]= new Apple();
 fruit[1]= new Banana(); //Banana has a protected peel() function returning a
 bool
 bool b;
 b=fruit[1].peal();
 Error: no property 'peel' for type 'project.fruitclass.Fruit'
 Error: function expected before (), not 1 of type int
 Error: cannot implicitly convert expression (cast(Banana)1()) of type
 'project.banana.Banana' to bool

from the list (private, protected, public) pick public. Note the difference between peel and peal. public YellowBanana: Banana { void doStuff() { bool e = peel(); //visible from derived //class when defined protected or public. } } Banana a = new Banana(); bool f = a.peel(); //visible only when public All non-static non-private non-template member functions are virtual. (Rule only valid in D) If you want to peel your fruit your fruit needs a peel member function, or else you need to cast it (dynamic_cast). You can make an abstract virtual function (pure virtual function). What kind of a programme are you making? Just curious.
Nov 20 2008
next sibling parent reply "Saaa" <empty needmail.com> writes:
 from the list (private, protected, public) pick public.
 Note the difference between peel and peal.

 public YellowBanana: Banana
 {
  void doStuff()
  {
     bool e = peel();   //visible from derived
                        //class when defined protected or public.
  }
 }

 Banana a = new Banana();
 bool f = a.peel();      //visible only when public

 All non-static non-private non-template member functions are virtual.
 (Rule only valid in D)

 If you want to peel your fruit your fruit needs a peel member function,
 or else you need to cast it (dynamic_cast). You can make an abstract
 virtual function (pure virtual function).

 What kind of a programme are you making? Just curious.

Nov 20 2008
parent reply Christopher Wright <dhasenan gmail.com> writes:
Saaa wrote:
 from the list (private, protected, public) pick public.
 Note the difference between peel and peal.

 public YellowBanana: Banana
 {
  void doStuff()
  {
     bool e = peel();   //visible from derived
                        //class when defined protected or public.
  }
 }

 Banana a = new Banana();
 bool f = a.peel();      //visible only when public

 All non-static non-private non-template member functions are virtual.
 (Rule only valid in D)


Informally, "virtual" means "can be overridden". It only applies to methods on classes. This definition is informal and ambiguous. According to __traits in d2, "virtual" means "might have a vtbl entry". A vtbl is a list of function pointers corresponding to the methods of a class. Each instance of that class has a pointer to the same list. Virtual dispatch just consists of pointing to a different vtbl with a different function in that slot. Anyway, the __traits definition maps to the following lemmas[1]: - static is not virtual - template is not virtual - private is not virtual On the other hand, final functions are virtual. If a final function does not override a virtual function, the compiler can turn it into a free function if that's more efficient. Or maybe not. If a final function overrides a virtual function, it will certainly end up in the class vtbl. Final functions are a bit questionable. If they override a virtual method in a base class, they should certainly be considered virtual, but you also sometimes need to know whether you can override a function. That is when it's not final and it is virtual. [1] It's a bit of a stretch to grant them this name, but if life gives you lemmas, make lemma-ade.
Nov 20 2008
parent reply "Saaa" <empty needmail.com> writes:
 Informally, "virtual" means "can be overridden". It only applies to
 methods on classes. This definition is informal and ambiguous.

vtable, right? How much of a difference can I expect? Because it doesn't look like a lot of work: just one single table lookup.
 According to __traits in d2, "virtual" means "might have a vtbl entry". A 
 vtbl is a list of function pointers corresponding to the methods of a 
 class. Each instance of that class has a pointer to the same list.

 Virtual dispatch just consists of pointing to a different vtbl with a 
 different function in that slot.

 Anyway, the __traits definition maps to the following lemmas[1]:
 - static is not virtual

 - template is not virtual

 - private is not virtual

 On the other hand, final functions are virtual. If a final function does 
 not override a virtual function, the compiler can turn it into a free 
 function if that's more efficient. Or maybe not. If a final function 
 overrides a virtual function, it will certainly end up in the class vtbl.

 Final functions are a bit questionable. If they override a virtual method 
 in a base class, they should certainly be considered virtual, but you also 
 sometimes need to know whether you can override a function. That is when 
 it's not final and it is virtual.

How does the compiler know that I want that?
 [1] It's a bit of a stretch to grant them this name, but if life gives you 
 lemmas, make lemma-ade.

Nov 20 2008
parent reply Christopher Wright <dhasenan gmail.com> writes:
Saaa wrote:
 Informally, "virtual" means "can be overridden". It only applies to
 methods on classes. This definition is informal and ambiguous.

vtable, right? How much of a difference can I expect? Because it doesn't look like a lot of work: just one single table lookup.

There are two issues, both relating to caching. First, your vtbl might not be in cache, which means an expensive memory lookup. Second, the cpu has a cache of instructions you're about to execute; with a non-virtual function, that's a fixed target, so the cpu can do better prefetching. In practice, your typeinfo is probably reasonably high in your cache, so it won't take very long. A smart compiler should probably put all the vtbls in the same region of memory, ideally arranged according to inheritance. (Maybe not, I'm not an expert.) Actually arranging this is probably quite impossible. At any rate, if your performance is bad, you'd be better off profiling. If profiling doesn't show anything interesting and you still need a minor performance boost, you can try marking everything as final. If your code consists entirely of function calls, you might get a 20-50% speed increase. If it's more typical code, maybe a 2% speed increase. (Judging by random microbenchmarks I've seen on the intarwebs.)
 Virtual dispatch just consists of pointing to a different vtbl with a 
 different function in that slot.


You make a method call. The compiler dispatches that to a particular concrete, free-floating function that happens to take a hidden parameter named 'this'. With virtual dispatch, you might call a different function depending on the type of 'this'.
 When I need to know whether I can override it, it becomes virtual?
 How does the compiler know that I want that?

If it's final, you can't override it. If you override something, your override can be final: class Base { /* virtual */ void foo () { writefln("Base.foo!"); } } class Final : Base { // I'm virtual, but you can't override me. final override void foo () { writefln("Final.foo!"); } } class Fail : Final { // Told you you can't override me. override void foo () { writefln("I don't even compile :("); } } The rest of what I was saying mainly applies to people using reflection to determine whether a function can be overridden.
Nov 20 2008
parent "Saaa" <empty needmail.com> writes:
Thanks !!
I miss university :'(


 Informally, "virtual" means "can be overridden". It only applies to
 methods on classes. This definition is informal and ambiguous.

vtable, right? How much of a difference can I expect? Because it doesn't look like a lot of work: just one single table lookup.

There are two issues, both relating to caching. First, your vtbl might not be in cache, which means an expensive memory lookup. Second, the cpu has a cache of instructions you're about to execute; with a non-virtual function, that's a fixed target, so the cpu can do better prefetching. In practice, your typeinfo is probably reasonably high in your cache, so it won't take very long. A smart compiler should probably put all the vtbls in the same region of memory, ideally arranged according to inheritance. (Maybe not, I'm not an expert.) Actually arranging this is probably quite impossible. At any rate, if your performance is bad, you'd be better off profiling. If profiling doesn't show anything interesting and you still need a minor performance boost, you can try marking everything as final. If your code consists entirely of function calls, you might get a 20-50% speed increase. If it's more typical code, maybe a 2% speed increase. (Judging by random microbenchmarks I've seen on the intarwebs.)
 Virtual dispatch just consists of pointing to a different vtbl with a 
 different function in that slot.


You make a method call. The compiler dispatches that to a particular concrete, free-floating function that happens to take a hidden parameter named 'this'. With virtual dispatch, you might call a different function depending on the type of 'this'.
 When I need to know whether I can override it, it becomes virtual?
 How does the compiler know that I want that?

If it's final, you can't override it. If you override something, your override can be final: class Base { /* virtual */ void foo () { writefln("Base.foo!"); } } class Final : Base { // I'm virtual, but you can't override me. final override void foo () { writefln("Final.foo!"); } } class Fail : Final { // Told you you can't override me. override void foo () { writefln("I don't even compile :("); } } The rest of what I was saying mainly applies to people using reflection to determine whether a function can be overridden.

Nov 20 2008
prev sibling parent "Jarrett Billingsley" <jarrett.billingsley gmail.com> writes:
On Thu, Nov 20, 2008 at 7:35 PM, Christopher Wright <dhasenan gmail.com> wrote:
 [1] It's a bit of a stretch to grant them this name, but if life gives you
 lemmas, make lemma-ade.

OhhhhhhhhhhhHHHHHHHHHHHHHHHHHHHHHH I think my head just exploded.
Nov 20 2008