How to create an extended ES6-class constructor from a provided base class and from additionally provided and to be mixed-in behavior?

huangapple go评论73阅读模式
英文:

How to create an extended ES6-class constructor from a provided base class and from additionally provided and to be mixed-in behavior?

问题

我尝试根据这里描述的想法编写一个基于 mixin 函数的方法来进行继承。方法 mixin 相当简单,但我在处理构造函数 mixin 时遇到了问题。

我试图编写一个函数,该函数接受一个类并返回一个具有扩展构造函数的新类。

这是我的示例:

function extend_constructor(original, extension) {
  let extended = function (...args) {
    console.log("扩展构造函数")
    original.prototype.constructor.apply(this, args)
    extension.apply(this, args)
  }
  Object.defineProperty(extended, 'name', Object.getOwnPropertyDescriptor(original, 'name'))
  extended.prototype = Object.create(original.prototype)
  Object.defineProperty(extended.prototype, 'constructor', {
    value: extended,
    writable: true,
    configurable: true
  })
  return extended
}

function extension(id) {
  console.log(`扩展: ${id}`)
}

它可以与函数类一起使用。

function Basefunc(id) {
  console.log(`基本函数: ${id}`)
}

new Basefunc(1)

const BasefuncEx = extend_constructor(Basefunc, extension)

new BasefuncEx(2)

但对于 ES6 类则会失败:

class Baseclass {
  constructor(id) {
    console.log(`基本类: ${id}`)
  }
}

new Baseclass(3)

const BaseclassEx = extend_constructor(Baseclass, extension)

new BaseclassEx(4)

错误信息为:

类构造函数 Baseclass 不能在没有 'new' 的情况下调用。

但我认为我不想使用 new,因为 new 将创建原始类的实例,并将原始构造函数应用于它。我希望将原始类的构造函数应用于扩展类的实例。我想知道如何在使用 new 的情况下实现这一点。

英文:

I tried to write a mixin function based on the ideas described here for inheritance. Method mixins are pretty easy, but I am struggling with constructor mixins.

I try to write a function, which takes a class and returns a new class, with an extended constructor.

This is my example:

function extend_constructor(original, extension) {
  let extended = function (...args) {
    console.log("extended constructor")
    original.prototype.constructor.apply(this, args)
    extension.apply(this, args)
  }
  Object.defineProperty(extended, 'name', Object.getOwnPropertyDescriptor(original, 'name'))
  extended.prototype = Object.create(original.prototype)
  Object.defineProperty(extended.prototype, 'constructor', {
    value: extended,
    writeable: true,
    configurable: true})
  return extended
}

function extension(id) {
  console.log(`Extension: ${id}`)
}

I works with function classes.

function Basefunc(id) {
  console.log(`Basefunc: ${id}`)
}

new Basefunc(1)

const BasefuncEx = extend_constructor(Basefunc, extension)

new BasefuncEx(2)

But fails with ES6 classes:

class Baseclass {
  constructor(id) {
    console.log(`Baseclass: ${id}`)
  }
}

new Baseclass(3)

const BaseclassEx = extend_constructor(Baseclass, extension)

new BaseclassEx(4)

The error is:

> TypeError: Class constructor Baseclass cannot be invoked without 'new'

But I think using new is not what I want, because new will create an instance of the original class and will apply the original constructor to it. I want to apply the original constructor of the original class to the instance of the extended class. And I am wondering how to do this with new.

答案1

得分: 2

以下是您提供的代码的翻译部分:

function createSubClassWithMixinBehavior(
  subClassName, SuperClass, withBehavior
) {
  return ({
    [subClassName]: class extends SuperClass {
      constructor(...args) {
        super(...args);
        withBehavior.apply(this, args);
      }
    },
  })[subClassName];
}

class BaseType {
  constructor(id) {
    console.log(`constructing the BaseType logs ... ${ id }`);
  }
}
function extension(id) {
  this.id = id;
  console.log(`applying / mixin-in the extension logs ... ${ id }`);
}
const baseType = new BaseType(3);
const subType = new (
  createSubClassWithMixinBehavior('SubType', BaseType, extension)
)(4);

console.log({
  baseType,
  subType,
  nameOfSuperClass: baseType.constructor.name,
  nameOfSubClass: subType.constructor.name,
});
.as-console-wrapper { min-height: 100%!important; top: 0; }
英文:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function createSubClassWithMixinBehavior(
  subClassName, SuperClass, withBehavior
) {
  return ({
    [subClassName]: class extends SuperClass {
      constructor(...args) {
        super(...args);
        withBehavior.apply(this, args);
      }
    },
  })[subClassName];
}

class BaseType {
  constructor(id) {
    console.log(`constructing the BaseType logs ... ${ id }`);
  }
}
function extension(id) {
  this.id = id;
  console.log(`applying / mixin-in the extension logs ... ${ id }`);
}
const baseType = new BaseType(3);
const subType = new (
  createSubClassWithMixinBehavior(&#39;SubType&#39;, BaseType, extension)
)(4);

console.log({
  baseType,
  subType,
  nameOfSuperClass: baseType.constructor.name,
  nameOfSubClass: subType.constructor.name,
});

<!-- language: lang-css -->

.as-console-wrapper { min-height: 100%!important; top: 0; }

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年2月9日 01:41:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/75389741.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定