【问题标题】:JavaScript Class Inheritance - fill method not workingJavaScript 类继承 - 填充方法不起作用
【发布时间】:2019-10-24 18:30:01
【问题描述】:

问题

我正在尝试创建两个类,其中一个是另一个的子类,并通过填充方法填充构造函数中的私有变量。但是,当使用fill方法填充父类私有变量时,这些变量会在初始化子类时消失。

class RequestFile {
    constructor (args = {}) {
        // this.to = args.to ? args.to : []
        // this.files = args.files ? args.files : []
        // this.body = args.body ? args.body : ''
    }
    fill ({to=[],files=[], subject='', body='', }) {
      this.to = to
      this.files = files
      this.subject = subject
      this.body = body
    }
}

class Mail extends RequestFile {
    constructor (args = {}) {
      super(args)
      this.fill(args)
    }
    fill ({cc='', draft=false, preview=true}) {
      this.cc = cc
      this.draft = draft
      this.preview = preview
    }
    to() {
      console.log(this.to)
    }
}
let mail = new Mail({
  to: [ 'name@gmail.com' ],
  files: [ 1111 ],
  subject: 'Sent from Node',
  body: 'test body  -- sent from node',
  cc: [ 'anotherone@gmail.com', 'another@gmail.com' ],
  draft: true,
  preview: true
})

console.log(mail)

以上输出如下:

Mail {
cc:(2) [...],
draft: true ,
preview: true
}

取消注释 RequestFile 类中的代码会产生不同的结果:

class RequestFile {
    constructor (args = {}) {
        this.to = args.to ? args.to : []
        this.files = args.files ? args.files : []
        this.body = args.body ? args.body : ''
    }
    fill ({to=[],files=[], subject='', body='', }) {
      this.to = to
      this.files = files
      this.subject = subject
      this.body = body
    }
}

Mail {
to:(1) [...],
files:(1) [...],
body: "test body -- sent from node" ,
cc:(2) [...],
draft: true ,
preview: true
}

理想情况下,我想依靠 fill 方法来填充类变量,我只是对为什么它在子类(Mail)中工作但在父类(RequestFile)中不起作用感到困惑

【问题讨论】:

  • 子类.fill() 必须显式调用父类版本。解构会变得很棘手,但你不必那样写。
  • 啊,我明白了,谢谢你的回复。我认为父类填充方法会自动调用,因为它是由构造函数调用的。
  • 必须显式调用父构造函数(通过super())。

标签: javascript inheritance constructor


【解决方案1】:

从子类中的fill()方法,调用基类继承的fill()方法。在应用对象解构之前,使用特殊的arguments 变量传递原始参数。

然后您甚至可以将对fill() 的调用移至基类构造函数,而不必从子类构造函数调用填充方法。

class RequestFile {
    constructor (args = {}) {
        this.fill(args);
    }

    fill ({to=[],files=[], subject='', body='', }) {
      this.to = to
      this.files = files
      this.subject = subject
      this.body = body
    }
}

class Mail extends RequestFile {
    constructor (args = {}) {
      super(args)
    }

    fill ({cc='', draft=false, preview=true}) {
      // pass on original parameter to base class fill method
      super.fill(arguments[0])
      this.cc = cc
      this.draft = draft
      this.preview = preview
    }
    to() {
      console.log(this.to)
    }
}

另一种解决方案是为基类和子类中的填充方法使用不同的名称:

class RequestFile {
    constructor (args = {}) {
        this.fillRequestFile(args);
    }

    fillRequestFile ({to=[],files=[], subject='', body='', }) {
      this.to = to
      this.files = files
      this.subject = subject
      this.body = body
    }
}

class Mail extends RequestFile {
    constructor (args = {}) {
      super(args)
      this.fillMail(args);
    }

    fillMail ({cc='', draft=false, preview=true}) {
      this.cc = cc
      this.draft = draft
      this.preview = preview
    }
    to() {
      console.log(this.to)
    }
}

【讨论】:

    【解决方案2】:
    class Mail extends RequestFile {
        constructor (args = {}) {
          super()
          super.fill(args)
          this.fill(args)
        }
        fill ({cc='', draft=false, preview=true}) {
          this.cc = cc
          this.draft = draft
          this.preview = preview
        }
        to() {
          console.log(this.to)
        }
    }
    

    【讨论】:

    • 这是一个糟糕的设计,因为后代类正在重新实现最初在基类中实现的行为。更好的方法是在基类和后代类中为 Fill() 函数使用不同的名称,或者让后代类中的 Fill() 方法调用基类中的 Fill() 方法(在您的情况下存在问题,因为论据解构)
    • 好的,你的回答很有道理。我不得不多读一点文档来理解为什么第一种方法有效。谢谢顺便说一句!参考:javascript.info/class-inheritance
    猜你喜欢
    • 2014-07-09
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 1970-01-01
    相关资源
    最近更新 更多