2015-06-27 3 views
1

Чтения, например, из typescript manual:пример наследования от машинописи ручного

class Animal { 
    name:string; 
    constructor(theName: string) { this.name = theName; } 
    move(meters: number = 0) { 
     alert(this.name + " moved " + meters + "m."); 
    } 
} 

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

class Horse extends Animal { 
    constructor(name: string) { super(name); } 
    move(meters = 45) { 
     alert("Galloping..."); 
     super.move(meters); 
    } 
} 

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

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

Речь идет о линии var tom: Animal = new Horse("Tommy the Palomino");:

  • Как я понимаю tom является Animal со свойствами Horse. Это правильно?

  • Какой смысл делать это таким образом? Не объявлять как var tom: Horse = ...?

  • Имея только одну версию, чтобы дать ему возможность разлагаться/меняться/развиваться до Snake или любого другого Animal. Я прав?

  • ... или, может быть, это только опечатка?

ответ

2

В приведенном выше примере, Animal является суперкласс (называемые также базовый класс или родительский класс) обоих Horse и Snake. Соответственно, Horse и Snake являются подклассы (производные классы) of Animal.

При объявлении подклассов:

class Snake extends Animal 
... 
class Horse extends Animal 

Вы говорите компилятору, что любой каждый Snake и каждый Horse находится в самом деле, Animal а. Это делает Animal более широкой категорией в «мире» программы. Snake и Horse будет унаследовать свойства Animal, но они могут изменить их (и/или добавить свои собственные), чтобы быть более специализированным.

  • tom «s декларация сообщает компилятору, что переменная будет принимать любые Animal. Как мы видели ранее, Horse является Animal, поэтому компилятор пропускает его.

  • Следовательно, они иллюстрируют тот факт, что всякий раз, когда член любого суперкласса ожидается в любом выражении, допустим один член любого из его подклассов. Это называется covariance.

  • В самом буквальном смысле, нет эволюционирующих или посвященных. Линия

    tom: Animal = new Horse("Tommy the Palomino");

    первый вызывает новый объект Horse будет создан. Затем объект присваивается переменной tom, но это присвоение не изменяет свойства объекта.Если вы запустили пример, вы увидите, что вызов horse.move() фактически вызывает версию Horse метода move, в котором сообщается, что «Томми Паломино переместил 45 м».

    Единственный заметный побочный эффект назначения Horse к Animal является то, что переменный, будучи наиболее общего типа, не знал бы ни специализированных свойства Horse. Он знает только, что общего у всех Animal s. Скажем Horse был объявлен как это:

    class Horse extends Animal { 
        constructor(name: string) { super(name); } 
        move(meters = 45) { 
         //... 
        } 
        swat_fly() { /* ... */ } 
    } 
    

    Вы не могли бы назвать tom.swat_fly(). Если вы этого захотите, вам нужно либо ввести тип tom (например: (<Horse>tom).swat_fly()), либо объявить его как Horse, а не как Animal. Но я повторяю: свойства объекта не меняются на суперкласс.

  • Так что нет, это не опечатка :)