www.digitalmars.com         C & C++   DMDScript  

D - Feature request? - virtual variables

reply "anderson" <anderson badmama.com.au> writes:
Does D support virtual variables?

By this I mean, can variables be coverted to some sub-type variable.

ie

class A
{
 car X;

 void turnOnCar()
 {
   X.run();
 }

 X getCar()
 {
   return X;
 }
}

class B
{
  holden X; // X is coverted to type holden
}

If the above breaks existing code, then you could always use the keyword
virtual.  I suppose pointers could be used for this ability, but they are
more messy and less effecient.

I think it would be useful for things like an extendable enumeration class .
Mar 04 2003
parent reply "anderson" <anderson badmama.com.au> writes:
"anderson" <anderson badmama.com.au> wrote in message
news:b43mjt$10r0$1 digitaldaemon.com...
 Does D support virtual variables?

 By this I mean, can variables be coverted to some sub-type variable.

 ie

 class A
 {
  car X;

  void turnOnCar()
  {
    X.run();
  }

  X getCar()
  {
    return X;
  }
 }

car getCar() { return X; } whoops.
 class B
 {
   holden X; // X is coverted to type holden
 }

 If the above breaks existing code, then you could always use the keyword
 virtual.  I suppose pointers could be used for this ability, but they are
 more messy and less effecient.

 I think it would be useful for things like an extendable enumeration class


Mar 05 2003
parent reply Norbert Nemec <nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM> writes:
That gives you a fundamental problem:

main {
        B special = new B;
        A general = A;
        car mycar = new car;
        A.X = mycar;
        holden myholden = B.X;  
        // The object created as car has become a holden!!!!!!!
};

The problem is inherent to the concept you are proposing. A variable type
always is a input parameter (of the writer) and a output parameter (of the
reader) so you can never change its type in a subclass without breaking
the interface of the parent class.

Ciao,
Nobbi



anderson wrote:

 
 "anderson" <anderson badmama.com.au> wrote in message
 news:b43mjt$10r0$1 digitaldaemon.com...
 Does D support virtual variables?

 By this I mean, can variables be coverted to some sub-type variable.

 ie

 class A
 {
  car X;

  void turnOnCar()
  {
    X.run();
  }

  X getCar()
  {
    return X;
  }
 }

car getCar() { return X; } whoops.
 class B
 {
   holden X; // X is coverted to type holden
 }

 If the above breaks existing code, then you could always use the keyword
 virtual.  I suppose pointers could be used for this ability, but they are
 more messy and less effecient.

 I think it would be useful for things like an extendable enumeration
 class



Mar 05 2003
parent reply "anderson" <anderson badmama.com.au> writes:
"Norbert Nemec" <nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM> wrote
in message news:b4592g$1trq$1 digitaldaemon.com...
 That gives you a fundamental problem:

 main {
         B special = new B;
         A general = A;
         car mycar = new car;
         A.X = mycar;

Did you mean? general.X = mycar;
         holden myholden = B.X;

holden myholden = special.X;
         // The object created as car has become a holden!!!!!!!

 };

 The problem is inherent to the concept you are proposing. A variable type
 always is a input parameter (of the writer) and a output parameter (of the
 reader) so you can never change its type in a subclass without breaking
 the interface of the parent class.

I'm probably just dumb, but I can't see what your talking about here. Holden should be a sub class of car, therefore all operations that apply to car should also work on holden. If car is being assigned to a holden such as X. A carH; B holdH; car mycar = new car; carH.X = mycar; holdH.X = mycar; //It should be in error. It'd be up to the programmer of A, to make sure this can never happen. Otherwise a copy constructor (in holden) could be used. The reader, can just perform a standard cast. Parhaps as I said before, the variable should be marked as virtual.
 Ciao,
 Nobbi



 anderson wrote:

 "anderson" <anderson badmama.com.au> wrote in message
 news:b43mjt$10r0$1 digitaldaemon.com...
 Does D support virtual variables?

 By this I mean, can variables be coverted to some sub-type variable.

 ie

 class A
 {
  car X;

  void turnOnCar()
  {
    X.run();
  }

  X getCar()
  {
    return X;
  }
 }

car getCar() { return X; } whoops.
 class B
 {
   holden X; // X is coverted to type holden
 }

 If the above breaks existing code, then you could always use the



 virtual.  I suppose pointers could be used for this ability, but they



 more messy and less effecient.

 I think it would be useful for things like an extendable enumeration
 class




Mar 06 2003
parent reply Norbert Nemec <nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM> writes:
Sorry, my example really was an absolute mess. Should have taken a little
more time for that...

You are right, the corrected code (using your names) would be:

main {
        B holdenH = new B;
        A carH = holdenH;  // (1)
        car mycar = new car;
        carH.X = mycar;
        holden myholden = holdenH.X;
        // The object created as car has become a holden!!!!!!!
};

My fundamental error really was in line (1) - see the corrected version
above. The point is:

Since B is a subclass of A, any object of type B must comply with the
complete interface of A. carH actually is a reference to a object of type
B, but since it looks like a "A", it will have to swallow any car that it
thrown at it and save it in X. B can't claim to be "A and more" if it
doesn't have the capability to swallow ordinary cars.

Of course this all only applies if X is a public variable. But then - with
private stuff you won't need that feature anyway, since you could just as
well define a new variable "holden Y" and rewrite all routines that used X
to use Y instead. (Maybe a little messy, but in a clean design, you'll need
it rarely anyway.)

Hope that made it a little clearer?

Ciao,
Nobbi
Mar 07 2003
parent reply "anderson" <anderson badmama.com.au> writes:
"Norbert Nemec" <nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM> wrote
in message news:b49rh5$1m08$1 digitaldaemon.com...
 Sorry, my example really was an absolute mess. Should have taken a little
 more time for that...

 You are right, the corrected code (using your names) would be:

 main {
         B holdenH = new B;
         A carH = holdenH;  // (1)
         car mycar = new car;
         carH.X = mycar;
         holden myholden = holdenH.X;

If you really wanted this ability, you'd probably create a copy constructor to covert a car to a holden. Or virtual variables could be treated as pointers that are initilized to the right type. Or make it an error.
         // The object created as car has become a holden!!!!!!!
 };

 My fundamental error really was in line (1) - see the corrected version
 above. The point is:

 Since B is a subclass of A, any object of type B must comply with the
 complete interface of A. carH actually is a reference to a object of type
 B, but since it looks like a "A", it will have to swallow any car that it
 thrown at it and save it in X. B can't claim to be "A and more" if it
 doesn't have the capability to swallow ordinary cars.

 Of course this all only applies if X is a public variable. But then - with
 private stuff you won't need that feature anyway, since you could just as
 well define a new variable "holden Y" and rewrite all routines that used X
 to use Y instead. (Maybe a little messy, but in a clean design, you'll

 it rarely anyway.)

Well, I was going to make it protected, but decided that this could also be done publicly (if need) with a few changes. The problem with redefining, is that you need (as you said) to rewrite all the routines and there's extra memory considerations. If you've derived 10 or 20 classes from the base class the cost of that can really add up. Generally I use a pointer to solve this problem which is cleaner then re-writting the the code every time, but not as clean as the method I suggest. It's kinda like a polymorphic way of templating. For example something like, class Error { Error1, Error2, Error3 } class Error2 : Error { Error4, Error5, } class A { virtual Error X; //Only need to write this once (in a real example there would be many other methods that use X) Error1 getErrors() { return X; } } class B : A { virtual Error2 X; } Anyway thanks for your explaination.
 Hope that made it a little clearer?

 Ciao,
 Nobbi

Mar 07 2003
parent "anderson" <anderson badmama.com.au> writes:
"anderson" <anderson badmama.com.au> wrote in message
news:b4a3ia$1ps1$1 digitaldaemon.com...
 "Norbert Nemec" <nobbi_at_theorie3.physik.uni-erlangen.de NOSPAM.COM>

 in message news:b49rh5$1m08$1 digitaldaemon.com...
 Sorry, my example really was an absolute mess. Should have taken a


 more time for that...

 You are right, the corrected code (using your names) would be:

 main {
         B holdenH = new B;
         A carH = holdenH;  // (1)
         car mycar = new car;
         carH.X = mycar;
         holden myholden = holdenH.X;

If you really wanted this ability, you'd probably create a copy

 to covert a car to a holden. Or virtual variables could be treated as
 pointers that are initilized to the right type. Or make it an error.

         // The object created as car has become a holden!!!!!!!
 };

 My fundamental error really was in line (1) - see the corrected version
 above. The point is:

 Since B is a subclass of A, any object of type B must comply with the
 complete interface of A. carH actually is a reference to a object of


 B, but since it looks like a "A", it will have to swallow any car that


 thrown at it and save it in X. B can't claim to be "A and more" if it
 doesn't have the capability to swallow ordinary cars.

 Of course this all only applies if X is a public variable. But then -


 private stuff you won't need that feature anyway, since you could just


 well define a new variable "holden Y" and rewrite all routines that used


 to use Y instead. (Maybe a little messy, but in a clean design, you'll

 it rarely anyway.)

Well, I was going to make it protected, but decided that this could also

 done publicly (if need) with a few changes.
 The problem with redefining, is that you need (as you said) to rewrite all
 the routines and there's extra memory considerations.  If you've derived

 or 20 classes from the base class the cost of that can really add up.
 Generally I use a pointer to solve this problem which is cleaner then
 re-writting the the code every time, but not as clean as the method I
 suggest.  It's kinda like a polymorphic way of templating.

 For example something like,

 class Error
 {
     Error1,
     Error2,
     Error3
 }

{ e Error1; e Error2; e Error3; }
 class Error2 : Error
 {
     Error4,
     Error5,
 }

class Error2 : Error { e Error4; e Error5; }
 class A
 {
     virtual Error X;

  //Only need to write this once (in a real example there would be many

 methods that use X)
     Error1 getErrors()
     {
         return X;
     }
 }

 class B : A
 {
     virtual Error2 X;
 }


 Anyway thanks for your explaination.

 Hope that made it a little clearer?

 Ciao,
 Nobbi


Mar 07 2003