Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/397.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 从ES6中的父类调用子方法_Javascript_Ecmascript 6 - Fatal编程技术网

Javascript 从ES6中的父类调用子方法

Javascript 从ES6中的父类调用子方法,javascript,ecmascript-6,Javascript,Ecmascript 6,从父类调用子方法是好的还是坏的做法 class Parent { constructor() { // if 'autoPlay' exists (was implemented) in chain if (this.autoPlay) { this.autoPlay(); // execute from parent } } } class ChildA extends Parent { auto

从父类调用子方法是好的还是坏的做法

class Parent {
    constructor() {
        // if 'autoPlay' exists (was implemented) in chain
        if (this.autoPlay) {
            this.autoPlay(); // execute from parent
        }
    }
}

class ChildA extends Parent {
    autoPlay() {
        console.log('Child');
    }
}

class ChildB extends Parent {
    // 'autoPlay' wasn't implemented
}

const childA = new ChildA();
const childB = new ChildB();

最好在父类中定义一个空的autoPlay实现,并在子类中重写它

class Parent {
  constructor() {
    this.autoPlay();
  }

  autoPlay() {

  }
}

class Child extends Parent {
  autoPlay() {
    console.log('Child');
  }
}

const child = new Child();
从父类调用子方法是一种好的做法吗

class Parent {
    constructor() {
        // if 'autoPlay' exists (was implemented) in chain
        if (this.autoPlay) {
            this.autoPlay(); // execute from parent
        }
    }
}

class ChildA extends Parent {
    autoPlay() {
        console.log('Child');
    }
}

class ChildB extends Parent {
    // 'autoPlay' wasn't implemented
}

const childA = new ChildA();
const childB = new ChildB();
是的,这是完全正常的做法。父类只调用实例的某个方法,如果子类重写了该方法,则调用子方法。然而,您通常不会进行这样一个“has my instance defined this method”测试,您只需要调用它。如果默认情况下不想执行任何操作,只需定义一个空方法(如@scipper的答案中所示)。如果要使方法抽象(强制子类重写它),可以不定义它,也可以定义引发适当异常的方法

从父构造函数调用子方法是一种不好的做法吗

(这在所有语言中都是一个问题)

构造函数的目的是初始化实例,而不是别的。将副作用的调用留给调用方。这将确保所有子构造函数也将完成其初始化

一个人为的例子:

class Parent {
    autoPlay() {
        this.play("automatically "); // call child method
    }
    play(x) {
        console.log(x+"playing default from "+this.constructor.name);
    }
}

class ChildA extends Parent {
    // does not override play
}
class ChildB extends Parent {
    constructor(song) {
        super();
        this.song = song;
    }
    play(x) {
        console.log(x+"playing "+this.song+" from ChildB");
    }
}

const child1 = new ChildA();
child1.autoPlay();
const child2 = new ChildB("'Yeah'");
child2.autoPlay();
请注意,如果
父级
构造函数调用了
自动播放
,那么这将不起作用。如果您不想在实例化后到处需要额外的方法调用,请使用helper函数。它甚至可能是一种静态方法:

class Parent {
    autoPlay() { … }
    play { … }
    static createAndAutoPlay(...args) {
        const instance = new this(...args);
        instance.autoPlay();
        return instance;
    }
}
…
const child1 = ChildA.createAndAutoPlay();
const child2 = ChildB.createAndAutoPlay("'Yeah'");

是的,父类与子类没有契约,相反。此外,将该方法移到父类中也没有意义。@LucasSteffen,每个扩展“parent”的类都有自己的“autoPlay”实现。因此,不可能将该方法移动到父级class@AliMamedov是否要求每个孩子都定义它?在这种情况下,您应该在父级中实现它,但会抛出一个错误。类似于
autoPlay(){throw new Error('autoPlay must implemented');}
。通常,从构造函数调用重写的方法不是一个好主意,因为您会遇到一系列初始化顺序问题。最佳实践是不从构造函数调用任何方法,而只进行实例初始化。创建实例的调用方应调用任何副作用,如
autoplay
。(否则,可以这样调用重写的方法,尽管您通常不需要“if defined”检查)子类应该有自己的
构造函数。不,这不是一个好的实践,除非类遵循一些接口,比如
init
方法。。也许这就是原因。或者是帽子
\_(ツ)_/'
不确定为什么会被否决。这是一个很好的示例。(+1来自我)在这种情况下,
父类
被称为抽象类定义(抽象,因为它本身实例化可能没有用处)。它提供方法的通用定义/接口,但不是所有方法的实现,并期望派生类完成实现。这是一种正常的面向对象设计技术,允许多个派生类在父类中共享一组实现,在某些情况下,父类本身从未被它本身。是否应该从构造函数调用
autoPlay()
是一个单独的问题。这行正确吗?
this.song=this;
还是应该是?
this.song=song
@SimonPuente您完全正确。感谢您的注意!Blast--所以如果我说,您有一个“getDefaultSettings()”我希望能够重写的方法,我将无法从抽象类构造函数调用它来适当地填充设置?(有意义,只是确保我完全正确)@slifty
getDefaultSettings
听起来它可能是一个静态方法,然后应该可以工作。它不能依赖于完全初始化的实例。