The super call must supply all parameters for base class. The constructor is not inherited. Commented out artist because I guess it is not needed when doing like this.
class StreetArtist extends Artist {
constructor(
name: string,
age: number,
style: string,
location: string,
public medium: string,
public famous: boolean,
public arrested: boolean,
/*public art: Artist*/
){
super(name, age, style, location);
console.log(`instantiated ${this.name}. Are they famous? ${famous}. Are they locked up? ${arrested}`);
}
}
Or if you intended the art parameter to populate base properties, but in that case I guess there isn't really a need for using public on art parameter as the properties would be inherited and it would only store duplicate data.
class StreetArtist extends Artist {
constructor(
public medium: string,
public famous: boolean,
public arrested: boolean,
/*public */art: Artist
){
super(art.name, art.age, art.style, art.location);
console.log(`instantiated ${this.name}. Are they famous? ${famous}. Are they locked up? ${arrested}`);
}
}
Answer from mollwe on Stack OverflowVideos
Another solution I eventually came up with, in addition to the ones provided by @iberbeu and @Nypan, is to add and intermediary initProps() method right before the call to scream():
class Person
{
public firstName: string;
constructor(firstName: string, props?: any)
{
this.firstName = firstName;
this.initProps(props);
this.scream();
}
protected initProps(props: any): void
{
}
protected scream(): void
{
console.log(this.firstName);
}
}
class Employee extends Person
{
public lastName: string;
constructor(firstName: string, lastName: string)
{
super(firstName, {lastName});
}
protected initProps(props: any): void
{
this.lastName = props.lastName;
}
protected scream(): void
{
console.log(this.firstName + ' ' + this.lastName);
}
}
Although I think both made a strong point and I should actually be using a factory pattern instead..
Am I doing a dumb thing here?
Yes you are. As iberbeu said in his comment a constructor should never do anything that does not have to do with constructing the object. It is a case of bad practice that can lead to all sorts of unexpected behaviour.
Are there better ways to arrange my code so I don't need to do this?
Using the solution you provided in your C option is the way to go here.
Is there some way to work around this error?
It depends on what you actually want to do. The normal way of doing things is illustrated by yourself in your C option. If the problem you are having is related to actually instantiating complex objects you might want to look in to builder/factory patterns. But if you actually want the constructors to do something you are simply doing it wrong; constructors are not ment to perform actions, they are there to construct objects and nothing else.
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);
You don't need to manually assign the name to a public variable. Using
public namein the constructor definition does this for you.You don't need to call
super(name)from the specialised classes.Using
this.nameworks.
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.
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:
The first logs the dynamic value for
super.namewhich is proceeded by the static string value"is Galloping...". The keywordthisreferences the "prototype chain" of the objecttom, and not the objecttomself. Because we have added a name property on theAnimal.prototype, horse will be outputted.The second log outputs
this.name, thethiskeyword refers to the the tom object itself.The third log is logged using the
movemethod of the Animal base class. This method is called from Horse class move method with the syntaxsuper.move(45);. Using thesuperkeyword in this context will look for amovemethod 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.
I've used it plenty of times, and I've read that it calls the constructor function of its parent class, but I'm not really grasping the concept of it to be honest. I know it's not a concept unique to JS, so if anyone has any good links/examples to explain it in other languages, that would also be great. I thought I understood it, but as I'm trying to learn more about OOP i seem to get more confused by the day lol.
Thanks