TypeScript:演练:无效

时间:2015-12-03 10:27:26

标签: inheritance typescript

http://www.typescriptlang.org/Playground上有一个关于固有的演练。代码有点修改为更友好。

class Animal {
    constructor(public name: string) { }
    move(meters: number) {
        console.log(this.name + " moved " + meters + "m.");
    }
}

class Snake extends Animal {
    constructor(name: string) { super(name); }
    move() {
        console.log("Slithering...");
        super.move(5);
    }
}

class Horse extends Animal {
    constructor(name: string) { super(name); }
    move() {
        console.log("Galloping...");
        super.move(45);
    }
}

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

sam.move();
tom.move(11);

第二个对象是动物

var tom: Animal = new Horse("Tommy the Palomino");
tom.move(11);

现在作为C#开发人员,我希望看到这种结果

Slithering...
Sammy the Python moved 5m.
Tommy the Palomino moved 11m.

所以不应该调用来自Horse的移动方法。我怎么看到不同的东西。

Slithering...
Sammy the Python moved 5m.
Galloping...
Tommy the Palomino moved 45m.
因为它似乎忽略了参数" 11"从:

tom.move(11);

并且正在从派生类运行方法。

关于这一点,我有两个问题。

  1. 为什么会发生这种情况或者这可能是一个错误
  2. 如果它的预期行为如何从动物类调用方法,只要我不想像这样创建动物对象。

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

1 个答案:

答案 0 :(得分:1)

  
      
  1. 为什么会发生这种情况或者这可能是个错误?
  2.   

你是对的。这在TypeScript中是不同的。

做类似的事情时:

(new MyClass()).overriddenMethod();

它是MyClass中定义的方法,无论如何都将被调用。

这是因为(在javascript中)不存在重写方法的事实;它实际上会被取代。

举个例子:

class Animal {
    move(meters: number) { console.log("Moved " + meters + "m."); }
}

class Snake extends Animal {
    move() { super.move(5); }
}

它编译为(为简单起见删除了_extends实现):

var Animal = (function () {
    function Animal() {
    }
    Animal.prototype.move = function (meters) { console.log("Moved " + meters + "m."); };
    return Animal;
})();
var Snake = (function (_super) {
    __extends(Snake, _super);
    function Snake() {
        _super.apply(this, arguments);
    }
    Snake.prototype.move = function () { _super.prototype.move.call(this, 5); };
    return Snake;
})(Animal); 

move上的Snake只会替换move上的Animal实施。在内部,您可以使用super调用父方法,但不会在类之外进行父类的转换。

所以能够做到:

var foo: Animal = new Snake("Some awesome snake");

简单地说Snake具有相同的“界面”(即它,有点像,看起来像Animal)但是如果你覆盖父类的方法你就永远无法取回它, 可以这么说。当转换为javascript时,获得这种多态性的能力会消失,其中所有类型的知识都被丢弃。

  
      
  1. 如果它的目的是如何从Animal Class调用方法   如果我不想像这样创建动物对象。
  2.   

您可以这样做:

class Animal {
    move(meters: number) { console.log("Moved " + meters + "m."); }
}

class Snake extends Animal {

    move(meters?: number) {
        super.move(meters != null ? meters : 5);
    }
}

甚至:

class Animal {
    move(meters: number) { console.log("Moved " + meters + "m."); }
}

class Snake extends Animal {

    move();
    move(meters: number);
    move(someRandomThing: MyNiceObject);
    move(meters: number, someRandomThing: MyNiceObject);
    move() {
        var args = arguments;
        if (args.length == 0) {
            super.move(3);
        }
        else if (args.length == 2) {
            // Do something related to..
            // move(meters: number, someRandomThing: MyNiceObject);
        }
        else {
            if (typeof(args[0]) === "number") {
                // move(meters: number);
            } else {
                // move(someRandomThing: MyNiceObject);
            }
        }
    }
}

所以..从经典的oo方法来看,这似乎有限(我来自c#,c ++等我自己)。但我很少注意到它,它仍然在一周的任何一天都是纯粹的javascript!