2016-03-29 1 views
3

Почему в коде ниже я получил неправильный this.name ссылка внутри абстрактного метода реализации?Зачем ошибаться this.propertyName ссылка внутри абстрактного метода реализации?

abstract class Abstract { 
    protected name: string; 

    constructor() { 
    this.abstractMethod(); 
    } 

    protected abstract abstractMethod(): void; 
} 

class Concrete extends Abstract { 
    protected name: string = 'Concrete'; 

    protected abstractMethod() { 
    console.log(this, this.name); // Concrete, undefined 
    } 
} 

new Concrete(); 

Link on example

+0

Уверены ли вы? Я не получаю сообщение об ошибке на ссылке ни на мою IDE. –

+0

Как правило, не рекомендуется вызывать виртуальные методы из конструктора в C#, java или javascript, поскольку инварианты типа могут ломаться. (см. сообщение Eric Lipperts, чтобы узнать, в чем проблема с ним, особенно раздел комментариев https://blogs.msdn.microsoft.com/ericlippert/2008/02/18/why-do-initializers-run-in-the-opposite -order-as-constructors-part-two /) –

ответ

1

Я действительно не знаю, что вы хотите достичь, но, возможно, это помогает, извините за мой английский

abstract class Abstract { 
    protected name: string; 

    constructor() { 
     //this.abstractMethod(); 
    } 

    protected abstract abstractMethod(): void; 
} 

class Concrete extends Abstract { 
    protected name: string = 'Concrete'; 

    constructor() { 
     super(); 
     this.abstractMethod(); 
    } 

    protected abstractMethod() { 
     console.log(this, this.name); 
    } 
} 

консоли:

Concrete { name: 'Concrete' } 'Concrete' 
4

Глядя на скомпилированный JavaScript может помочь в ситуациях, как это:

function Concrete() { 
    _super.apply(this, arguments); // calls this.abstractMethod() 
    this.name = 'Concrete'; 
} 

Задание не занимает места, пока после супер вызова-вызова Abstract-х конструктор - и так во время this.abstractMethod называется this.name is undefined.

+0

Какой лучший способ исправить это? –

+0

@ КачаловТимофей существует несколько способов, но, вероятно, лучше не называть абстрактный метод в конструкторе абстрактных классов. –

1

явление вы наблюдали предсказуемо, так как конструкторы выполняются в порядке от базовых классов до конкретных классов. Лучшее решение заключается в том, чтобы конструктор абстрактных классов обрабатывал свойство name:

abstract class Abstract { 

    constructor (protected name: string) { 
    this.abstractMethod(); 
    } 

    protected abstract abstractMethod(): void; 
} 

class Concrete extends Abstract { 
    constructor() { 
    super("Concrete"); 
    } 
    protected abstractMethod() { 
    console.log(this, this.name); // Concrete, undefined 
    } 
} 

new Concrete(); 
Смежные вопросы