Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript重写方法_Javascript_Oop_Overriding - Fatal编程技术网

JavaScript重写方法

JavaScript重写方法,javascript,oop,overriding,Javascript,Oop,Overriding,假设您拥有以下代码: function A() { function modify() { x = 300; y = 400; } var c = new C(); } function B() { function modify(){ x = 3000; y = 4000; } var c = new C(); } C = function () { var x = 10;

假设您拥有以下代码:

function A() {
    function modify() {
       x = 300;
       y = 400;
    }

    var c = new C();
}

function B() {
    function modify(){
       x = 3000;
       y = 4000;
    }

    var c = new C();
}

C = function () {
   var x = 10;
   var y = 20;

   function modify() {
      x = 30;
      y = 40;
   };

   modify();
   alert("The sum is: " + (x+y));
}
现在的问题是,是否有任何方法可以用
A
B
中的方法覆盖
modify
from
C
。在Java中,您可能会使用
super
-关键字,但在JavaScript中如何实现这样的效果呢?

上一次调用的
modify()
方法是在全局上下文中调用的 如果要重写
modify()
,首先必须继承
A
B

也许你正在尝试这样做:

在这种情况下,
C
继承
A

function A() {
    this.modify = function() {
        alert("in A");
    }
}

function B() {
    this.modify = function() {
        alert("in B");
    }
}

C = function() {
    this.modify = function() {
        alert("in C");
    };

    C.prototype.modify(); // you can call this method where you need to call modify of the parent class
}

C.prototype = new A();
在您的示例中,modify()是一个私有函数,只能在a、B或C定义中访问。您需要将其声明为

this.modify = function(){}

C没有对其父级的引用,除非您将其传递给C。如果C设置为从A或B继承,它将继承其公共方法(而不是像您定义的modify()那样继承其私有函数)。一旦C从其父级继承了方法,您就可以重写继承的方法。

编辑:从最初的答案编写到现在已经六年了,而且已经发生了很多变化

  • 如果您使用的是较新版本的JavaScript,可能是使用类似的工具编译的,您可以
  • 如果您使用的是或提供的类式组件构造函数,则需要在文档中查找该框架
  • 如果您使用ES5并使用原型手工制作“假”类,那么下面的答案仍然和以前一样正确
祝你好运


JavaScript继承看起来与Java有点不同。以下是本机JavaScript对象系统的外观:

// Create a class
function Vehicle(color){
  this.color = color;
}

// Add an instance method
Vehicle.prototype.go = function(){
  return "Underway in " + this.color;
}

// Add a second class
function Car(color){
  this.color = color;
}

// And declare it is a subclass of the first
Car.prototype = new Vehicle();

// Override the instance method
Car.prototype.go = function(){
  return Vehicle.prototype.go.call(this) + " car"
}

// Create some instances and see the overridden behavior.
var v = new Vehicle("blue");
v.go() // "Underway in blue"

var c = new Car("red");
c.go() // "Underway in red car"

不幸的是,这有点难看,并且它没有包含一种非常好的“超级”方法:您必须手动指定要调用的父类的方法。因此,有多种工具可以使创建类变得更好。尝试查看Prototype.js、Backbone.js或类似的库,这些库包含在js中执行OOP的更好语法。

除非您将所有变量设置为“公共”,即直接或通过
Prototype
属性将它们设置为
函数的成员

var C = function( ) {
    this.x = 10 , this.y = 20 ;
    this.modify = function( ) {
        this.x = 30 , this.y = 40 ;
        console.log("(!) C >> " + (this.x + this.y) ) ;
    } ;
} ;

var A = function( ) {
    this.modify = function( ) {
       this.x = 300 , this.y = 400 ;
       console.log("(!) A >> " + (this.x + this.y) ) ;
    } ;
} ;
    A.prototype = new C ;

var B = function( ) {
    this.modify = function( ) {
       this.x = 3000 , this.y = 4000 ;
       console.log("(!) B >> " + (this.x + this.y) ) ;
    } ;
} ;


new C( ).modify( ) ;
new A( ).modify( ) ;
new B( ).modify( ) ; 

你会注意到一些变化

最重要的是,对假定的“超级类”构造函数的调用现在隐式地包含在这一行中:

<name>.prototype = new C ;
将用该名称“覆盖”原始的
函数

最后,在
函数
声明中不能调用
修改
,因为当我们将假定的“超类”设置为假定的“子类”的
原型
属性时,将再次执行对“超类”的隐式调用

但是,这或多或少就是用JavaScript做这类事情的方式

嗯,


FK应该避免模仿经典OO,而是使用原型OO。一个很好的原型OO实用程序库是

与其覆盖方法和建立继承链(人们应该总是支持对象组合而不是对象继承),不如将可重用函数绑定到trait中,并用这些特性创建对象


由于这是谷歌的热门话题,我想给出一个最新的答案

使用可使继承和方法重写更容易:

'use strict';

class A {
    speak() {
        console.log("I'm A");
    }
}

class B extends A {
    speak() {
        super.speak();

        console.log("I'm B");
    }
}

var a = new A();
a.speak();
// Output:
// I'm A

var b = new B();
b.speak();
// Output:
// I'm A
// I'm B
在继承类中使用时,引用父类。此外,父类上的所有方法都绑定到子类的实例,因此您不必编写
super.method.apply(此)

至于兼容性:只显示主要玩家支持类的最新版本(大部分)。V8浏览器从今年1月就已经有了它们(Chrome和Opera),而使用SpiderMonkey JS引擎的Firefox将在下个月正式发布Firefox45。在移动端,Android仍然不支持该功能,而五个月前发布的iOS 9则部分支持

幸运的是,有一个JS库可以将Harmony代码重新编译成ES5代码。类和ES6中的许多其他酷特性可以使Javascript代码更具可读性和可维护性。

函数A(){
var c=新的c();
c、 modify=函数(){
c、 x=123;
c、 y=333;
}
c、 sum();
}
函数B(){
var c=新的c();
c、 modify=函数(){
c、 x=999;
c、 y=333;
}
c、 sum();
}
C=函数(){
这是x=10;
这个y=20;
this.modify=函数(){
这个x=30;
这个y=40;
};
this.sum=函数(){
这是modify();
log(“总和是:”+(this.x+this.y));
}
}
A();

B()
modify
不是一个方法,而是一个嵌套函数——这两者之间有区别……在Java中,可以使用
super
关键字访问超类的非私有字段和方法。您不能使用它来覆盖它们。修改是一个本地函数。javascriptlocal/private中没有private,这不是一回事吗,只是一个不同的术语?你没有回答这个问题。这应该是一个注释。@FK82让我们看看
.prototype=new C隐藏原型的所有成员anyway@Raynos:有。也就是说,如果不实例化
C
对象,所有继承的
对象
将在
C
中共享同一个成员。因此,在
A
中更改
x
将在
C
中更改
x
,从而在
B
中更改
x
。这显然是不受欢迎的。你没有抓住重点。您可以删除该行,代码仍将保持不变function@Raynos:恐怕你没有说到点子上我们希望
A
B
继承自
C
。如果那条线不见了,情况就不是这样了。事实上,
A
B
唯一的原型都是“影子”型的
var modifyA = {
    modify: function() {
        this.x = 300;
        this.y = 400;
    }
};

var modifyB = {
    modify: function() {
        this.x = 3000;
        this.y = 4000;
    }
};

C = function(trait) {
    var o = Object.create(Object.prototype, Trait(trait));

    o.modify();
    console.log("sum : " + (o.x + o.y));

    return o;
}

//C(modifyA);
C(modifyB);
'use strict';

class A {
    speak() {
        console.log("I'm A");
    }
}

class B extends A {
    speak() {
        super.speak();

        console.log("I'm B");
    }
}

var a = new A();
a.speak();
// Output:
// I'm A

var b = new B();
b.speak();
// Output:
// I'm A
// I'm B