4

给定类 A 和类 B,其中类 B 继承自类 A ...

// Define class A
dojo.declare("mynamespace.A",null,{
    myMethodA: function() { this.myMethodB() }
});

// Define class B
dojo.declare("mynamespace.B",mynamespace.A,{
    myMethodB: function() {}
});

在 A 类(父类)范围内调用 this.myMethodB() 是否合法?我在一个软件中看到过这个,我不明白。我知道在 Java 中,除非您将 A 类型转换为 B,否则这是不可能的。但是 dojo 有什么不同吗?

4

3 回答 3

1

JavaScript 中没有静态编译,因此,正如@akonsu 所提到的,它在技术上是可行的,但它不是一个可以遵循的模式:

var a = new mynamespace.A();
a.myMethodA(); // ilegal: Uncaught TypeError: Object [object Object] has no method 'methodB' 

var b = new mynamespace.B();
b.myMethodA() // legal

您还可以在 JavaScript 的给定范围内执行方法/函数,即作为给定对象的方法:

a.myMethodA.call(b); // legal as `this` inside `myMethodA` will be referencing to object `b`

实际上,我认为可以用你从 Java 中知道mynamespace.A的抽象方法来模拟抽象类。myMethodBmynamespace.A当子类化时,子类应该实现myMethodB. 但是这样做很容易出错,我会以更健壮的方式来做:

// Define class A
dojo.declare("mynamespaca.A", null, {

    myMethodA: function() {
        this.myMethodB();
    },

    myMethodB: function() {
        // abstract method
        console.warn("Abstract method [myMethodB] was not implemented.");
        // or: throw new Error("Abstract method [myMethodB] was not implemented.");
    }   

});


// Define class B
dojo.declare("mynamespace.B", mynamespace.A, {

    myMethodB: function() {
        // implement abstract method here
    }

});
于 2012-05-18T21:17:35.980 回答
1

这个问题的流行语是this.inherited(arguments); 你的问题是调用一个不在当前继承范围内的方法 - 并且一个真正的面向对象的程序员会被称为无效..但是它是可能的(仍然)因为加载器声明了全局范围内的所有内容,例如你可以访问任何模块通过mynamespace.X 然后添加原型.theMethod。

一旦你像在 mynamespace.B 中一样拥有继承,A 和 B 的所有功能都是“this”范围的。它就像是东西的合并散列,比如说for all methods and variables in A do set instance B[key] = property A[key]

但是,如果您遇到覆盖,其中属性为“类”A 和 B 的原型 - 声明/构造链中有一种机制允许调用“超级”(或父类,遵循您的符号)。

对于特殊属性构造函数来说,继承冒泡[期间]总是如此。

对于仅声明一次的任何方法,如果它不是继承的方法,您就不能自己调用​​它 - 然后可以通过“this”访问它

对于任何具有覆盖的方法,函数 'this.inherited(arguments);' 将向您向上发送一个刻度线到当前的被调用者父类。看看这里的扩展小提琴

var AClass = dojo.declare("mynamespace.A", null, {
    constructor: function(args) {
        this.overriddenMethod();
    },
    overriddenMethod: function() {

    }
});
var BClass = dojo.declare("mynamespace.B", [AClass], {

    constructor: function() {  },

    overriddenMethod: function() {
        // call super before anything else is processed in this method
        // by placing following call you can control function callflow
        this.inherited(arguments);
    }
});

// will call A.constructor, then A.overriddenMethod
new AClass();

// will call B.constructor, A.constructor, B.overriddenMethod and then
//  A.overriddenMethod via the call to super
//  in B.overriddenMethod which A.constructor 
//  calls (note that A.constructor callflow 'aims' B.override not A.override)
new BClass();
于 2012-05-19T11:08:58.570 回答
0

您可以使用原型对象调用任何方法。

myMethodA: function() { mynamespace.B.prototype.myMethodB(); }

这是一个工作示例:

http://jsfiddle.net/cswing/7cBJm/

于 2012-05-18T20:46:34.133 回答