www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Getting "this" to work similar to "self" in Python

reply "nurfz" <derp herp.com> writes:
How could I get this D code to work similar to this Python code?

So, here is the D code:

     import std.stdio;

     class Vehicle {
         int speed;
         void printSpeed() {
             writeln(this.speed);
         }
     }

     class Airplane: Vehicle {
         int speed = 100;
     }

     int main() {
         auto v = new Vehicle();
         auto a = new Airplane();

         v.printSpeed();  // 0
         a.printSpeed(); // 0 not 100

         writeln(v.speed); // 0
         writeln(a.speed); // 100
     }

Here is the Python code:

     class Vehicle:
         speed = 0
         def printSpeed(self):
             print(self.speed)

     class Airplane(Vehicle):
         speed = 100

     if __name__ == "__main__":
         v = Vehicle()
         a = Airplane()

         v.printSpeed()  # 0
         a.printSpeed()  # 100

         print(v.speed)  # 0
         print(a.speed)  # 100

I guess I'm confused as to why the D code isn't acting similar to 
the Python code in the sense that you would expect "this" to 
reference the "speed" property of the current instance and not 
statically reference the parent.  Am I having these issues 
because these attributes are being initialized statically?

Would using constructors be the way to go about this? I suppose 
I'm just trying to find a way to implement fairly clean and 
intuitive object oriented inheritance that isn't crippled by 
getters/setters, is resolved at compile time, and doesn't impose 
any kind of runtime cost other than what you would assume is 
associated with fundamental level OOP.

Sorry for the long winded post, but this has just been confusing 
me to no end.  Hopefully you guys can help me out! :)
Jul 22 2015
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 22 July 2015 at 22:22:02 UTC, nurfz wrote:
 How could I get this D code to work similar to this Python code?

 So, here is the D code:

     import std.stdio;

     class Vehicle {
         int speed;
         void printSpeed() {
             writeln(this.speed);
         }
     }

     class Airplane: Vehicle {
         int speed = 100;
     }

     int main() {
         auto v = new Vehicle();
         auto a = new Airplane();

         v.printSpeed();  // 0
         a.printSpeed(); // 0 not 100

         writeln(v.speed); // 0
         writeln(a.speed); // 100
     }

 Here is the Python code:

     class Vehicle:
         speed = 0
         def printSpeed(self):
             print(self.speed)

     class Airplane(Vehicle):
         speed = 100

     if __name__ == "__main__":
         v = Vehicle()
         a = Airplane()

         v.printSpeed()  # 0
         a.printSpeed()  # 100

         print(v.speed)  # 0
         print(a.speed)  # 100

 I guess I'm confused as to why the D code isn't acting similar 
 to the Python code in the sense that you would expect "this" to 
 reference the "speed" property of the current instance and not 
 statically reference the parent.  Am I having these issues 
 because these attributes are being initialized statically?

 Would using constructors be the way to go about this? I suppose 
 I'm just trying to find a way to implement fairly clean and 
 intuitive object oriented inheritance that isn't crippled by 
 getters/setters, is resolved at compile time, and doesn't 
 impose any kind of runtime cost other than what you would 
 assume is associated with fundamental level OOP.

 Sorry for the long winded post, but this has just been 
 confusing me to no end.  Hopefully you guys can help me out! :)
Fields of classes are not in any way polymorphic in D (this is the same as C++ and I think java too). Base class members can be accessed like so: class Vehicle { int speed; void printSpeed() { writeln(this.speed); } } class Airplane: Vehicle { this() { Vehicle.speed = 100; } } or if you really want to use the same variable name: class Airplane: Vehicle { alias speed = Vehicle.speed; this() { speed = 100; } } You can even automatically do that sort of thing by various means, the shortest/simplest way I can think of would be: class Airplane: Vehicle { private property Vehicle base() { return this; } alias base this; this() { speed = 100; } }
Jul 22 2015
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Wednesday, 22 July 2015 at 22:52:22 UTC, John Colvin wrote:
 On Wednesday, 22 July 2015 at 22:22:02 UTC, nurfz wrote:
 [...]
Fields of classes are not in any way polymorphic in D (this is the same as C++ and I think java too). Base class members can be accessed like so: class Vehicle { int speed; void printSpeed() { writeln(this.speed); } } class Airplane: Vehicle { this() { Vehicle.speed = 100; } } or if you really want to use the same variable name: class Airplane: Vehicle { alias speed = Vehicle.speed; this() { speed = 100; } } You can even automatically do that sort of thing by various means, the shortest/simplest way I can think of would be: class Airplane: Vehicle { private property Vehicle base() { return this; } alias base this; this() { speed = 100; } }
Ok literally ignore all of that, I'm an idiot. speed is accessible directly, without Vehicle prefix, both from inside Airplane and outside. However, if you declare another variable Airplane.speed, it will shadow* Vehicle.speed, leading to the behaviour you see. Use a constructor instead of declaring a new variable with the same name. *as opposed to override or aliasing It really shows how little I use classes in D...
Jul 23 2015
prev sibling next sibling parent reply Jonathan M Davis via Digitalmars-d-learn writes:
On Wednesday, July 22, 2015 22:22:00 nurfz via Digitalmars-d-learn wrote:
 How could I get this D code to work similar to this Python code?

 So, here is the D code:

      import std.stdio;

      class Vehicle {
          int speed;
          void printSpeed() {
              writeln(this.speed);
          }
      }

      class Airplane: Vehicle {
          int speed = 100;
      }

      int main() {
          auto v = new Vehicle();
          auto a = new Airplane();

          v.printSpeed();  // 0
          a.printSpeed(); // 0 not 100

          writeln(v.speed); // 0
          writeln(a.speed); // 100
      }

 Here is the Python code:

      class Vehicle:
          speed = 0
          def printSpeed(self):
              print(self.speed)

      class Airplane(Vehicle):
          speed = 100

      if __name__ == "__main__":
          v = Vehicle()
          a = Airplane()

          v.printSpeed()  # 0
          a.printSpeed()  # 100

          print(v.speed)  # 0
          print(a.speed)  # 100

 I guess I'm confused as to why the D code isn't acting similar to
 the Python code in the sense that you would expect "this" to
 reference the "speed" property of the current instance and not
 statically reference the parent.  Am I having these issues
 because these attributes are being initialized statically?

 Would using constructors be the way to go about this? I suppose
 I'm just trying to find a way to implement fairly clean and
 intuitive object oriented inheritance that isn't crippled by
 getters/setters, is resolved at compile time, and doesn't impose
 any kind of runtime cost other than what you would assume is
 associated with fundamental level OOP.

 Sorry for the long winded post, but this has just been confusing
 me to no end.  Hopefully you guys can help me out! :)
Variables are not polymorphic. Only public or protected member functions are polymorphic. If you want to override behavior in a derived class, you have to use a function. And generally, it's not good practice to either have member variables be public or to reuse their names in derived classes. Making them public breaks encapsulation, and reusing names makes it too easy to confuse which name you're dealing with. A related question on SO: http://stackoverflow.com/questions/31436506 - Jonathan M Davis
Jul 22 2015
parent reply "nurfz" <derp herp.com> writes:
Hmm, is there a specific reason aside from the encapsulation 
violation?  It seems needlessly complicated.  If you have 
someone/something that has direct access to your source code, 
isn't a getter/setter the least of your concerns?  Does the 
 property decorator incur a large runtime cost?
Jul 22 2015
parent Jonathan M Davis via Digitalmars-d-learn writes:
On Wednesday, July 22, 2015 23:19:35 nurfz via Digitalmars-d-learn wrote:
 Hmm, is there a specific reason aside from the encapsulation
 violation?  It seems needlessly complicated.  If you have
 someone/something that has direct access to your source code,
 isn't a getter/setter the least of your concerns?
It has nothing to do with people having access to your source code. It's leaking how your class is implemented when you provide access to its member variables, which makes it so that code that uses it is more likely to depend on how it's currently implemented, and it makes it harder to change your code later. Users of your class should not depend on the internal implementantion of that class, since it creates unnecessary dependencies. Search on "high cohesion" and "low coupling," and you'll find stuff talking about how your code is more maintainable and of better quality when internals are kept internal, and dependencies across types are kept to a minimum. And remember that just because a getter/setter or property function happens to currently wrap a member variable, doesn't mean that it will later. For instance, you may need to change your code later so that the value in question is actually calculated rather than stored directly in the class. If the member variable is public, then making that change will break all code that uses that member variable, whereas if it's accessed via getters and setters (or property functions), then all of the code that uses that class will continue to work as it did before, which could save you a fair bit of time and effort, and if your code is part of an API that's publicly available, then you avoid breaking a lot of other people's code. And even if your getter/setter/property function will always wrap a member variable, it could be that you'll need to add code to the function(s) later that does extra checks, or sets another variable, or calls another function in addition to getting the current value of the member variable or setting it to a new value. It may not always simply access the variable. If you've made the member variable public, you'll be forced to break existing code when you need to wrap it in a function later. It's just good practice to make all of your member variable private and not provide direct access to any of them. It'll save you from pain later when you have to change how your class works, even if it's as simple as adding log messages. Even worse in D, invariants get called before and after a public member function is called. They don't get called when you access a public member variable. So, if you have a public member variable in a class with an invariant, you're just shooting yourself in the foot, because you can't guarantee the invariant anymore. It's not getting called when the member variable is accessed, and the code accessing it can do whatever it wants to it, including violate the invariant, and you won't catch it until a public member function gets called later, which could be in completely unrelated code. If you start searching for encapsulation and programming, or encapsulation and OOP, or data encaplusation, or anything like unto it, you will very quickly find a lot of stuff telling you to never make your member variables public. It's commonly considered bad practice in languages like C++, Java, C#, D, etc. because it's a mantainance problem when you do, and it really doesn't play well with OOP, since very few languages that support OOP have polymorphic variables (since to do that, you need wrap their access in function calls internally anyway).
 Does the  property decorator incur a large runtime cost?
property is only applicable to functions and has no effect on the runtime cost, though if a function is not inlined, then it will cost more than accessing a variable directly. So, if your question is whether wrapping member variable access in a getter/setter or a property function costs more, then that depends on whether the call gets inlined. If the call is inlined, then the cost is the same, and if they're not virtual one line functions are going to be inlined if you compile with -inline (which you would normally use in a release build). And if you're comparing with python, D would win regardless, because the only way that python can have polymorphic variables is by looking them up rather than simply accessing them directly as occurs in a language like D, C++, Java, etc. So, python is essentially always wrapping your variable accesses in getters and setters. - Jonathan M Davis
Jul 22 2015
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2015-07-23 00:22, nurfz wrote:

I think you got overly complicated answers.

 I guess I'm confused as to why the D code isn't acting similar to the
 Python code in the sense that you would expect "this" to reference the
 "speed" property of the current instance and not statically reference
 the parent.  Am I having these issues because these attributes are being
 initialized statically?
No, it's not because they're statically initialized. It's because fields are not polymorphic.
 Would using constructors be the way to go about this? I suppose I'm just
 trying to find a way to implement fairly clean and intuitive object
 oriented inheritance that isn't crippled by getters/setters, is resolved
 at compile time, and doesn't impose any kind of runtime cost other than
 what you would assume is associated with fundamental level OOP.
Either you can set the value in the constructor or turn "speed" in to a method/property. I think it's easiest to set it in the constructor: class Airplane : Vehicle { this() { speed = 100; } } -- /Jacob Carlborg
Jul 22 2015