Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing member of base class

Tags:

typescript

See the inheritance example from the playground on the TypeScript site:

class Animal {
  public name;
  constructor(name) {
    this.name = name;
  }
  move(meters) {
    alert(this.name + " moved " + meters + "m.");
  }
}

class Snake extends Animal {
  constructor(name) {
    super(name);
  }
  move() {
    alert("Slithering...");
    super.move(5);
  }
}

class Horse extends Animal {
  constructor(name) {
    super(name);
  }
  move() {
    alert(super.name + " is Galloping...");
    super.move(45);
  }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);

I have changed one line of code: the alert in Horse.move(). There I want to access super.name, but that returns just undefined. IntelliSense is suggesting that I can use it and TypeScript compiles fine, but it does not work.

Any ideas?

like image 620
Jaap Avatar asked Oct 29 '12 12:10

Jaap


People also ask

How do you access data members of base class?

You can use both a structure and a class as base classes in the base list of a derived class declaration: If the derived class is declared with the keyword class , the default access specifier in its base list specifiers is private .

Can base class access derived members?

A base class's private members are never accessible directly from a derived class, but can be accessed through calls to the public and protected members of the base class.

Can you access a protected member of a base class from a member function of the derived class derived in private mode?

Protected members in a class are similar to private members as they cannot be accessed from outside the class. But they can be accessed by derived classes or child classes while private members cannot.

Which class members can be accessed by the base class and the derived class?

Explanation: The friend function of a class can access the non-private members of base class. The reason behind is that the members of base class gets derived into the derived class and hence become members of derived class too. Hence a friend function can access all of those.


2 Answers

Working example. Notes below.

class Animal {
    constructor(public name) {
    }

    move(meters) {
        alert(this.name + " moved " + meters + "m.");
    }
}

class Snake extends Animal {
    move() {
        alert(this.name + " is Slithering...");
        super.move(5);
    }
}

class Horse extends Animal {
    move() {
        alert(this.name + " is Galloping...");
        super.move(45);
    }
}

var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");

sam.move();
tom.move(34);
  1. You don't need to manually assign the name to a public variable. Using public name in the constructor definition does this for you.

  2. You don't need to call super(name) from the specialised classes.

  3. Using this.name works.

Notes on use of super.

This is covered in more detail in section 4.9.2 of the language specification.

The behaviour of the classes inheriting from Animal is not dissimilar to the behaviour in other languages. You need to specify the super keyword in order to avoid confusion between a specialised function and the base class function. For example, if you called move() or this.move() you would be dealing with the specialised Snake or Horse function, so using super.move() explicitly calls the base class function.

There is no confusion of properties, as they are the properties of the instance. There is no difference between super.name and this.name - there is simply this.name. Otherwise you could create a Horse that had different names depending on whether you were in the specialized class or the base class.

like image 118
Fenton Avatar answered Oct 05 '22 06:10

Fenton


You're using the keywords super and this incorrectly. Below is an example that demonstrates them being correctly.

    class Animal {
        public name: string;

        constructor(name: string) { 
            this.name = name;
        }

        move(meters: number) {
            console.log(this.name + " moved " + meters + "m.");
        }
    }
    
    class Horse extends Animal {
        move() {
            console.log(super.name + " is Galloping...");
            console.log(this.name + " is Galloping...");
         
            super.move(45);
        }
    }
    
    var tom: Animal = new Horse("Tommy the Palomino");
    
    Animal.prototype.name = 'horseee'; 
    
    tom.move(34);
    // Outputs:
    
    // horseee is Galloping...
    // Tommy the Palomino is Galloping...
    // Tommy the Palomino moved 45m.

Explanation:

  1. The first logs the dynamic value for super.name which is proceeded by the static string value "is Galloping...". The keyword this references the "prototype chain" of the object tom, and not the object tom self. Because we have added a name property on the Animal.prototype, horse will be outputted.

  2. The second log outputs this.name, the this keyword refers to the the tom object itself.

  3. The third log is logged using the move method of the Animal base class. This method is called from Horse class move method with the syntax super.move(45);. Using the super keyword in this context will look for a move method on the prototype chain which is found on the Animal prototype.

Remember TS still uses prototypes under the hood and the class and extends keywords are just syntactic sugar over prototypical inheritance.

like image 38
Willem van der Veen Avatar answered Oct 05 '22 07:10

Willem van der Veen