【问题标题】:Can we change the constructor behavior using typescript class decorators? I mean to change number of parameters in constructor我们可以使用 typescript 类装饰器来更改构造函数的行为吗?我的意思是改变构造函数中的参数数量
【发布时间】:2016-08-29 05:05:55
【问题描述】:

打字稿代码

@logClass // this is my decorator
class Person { 

  public name: string;
  public surname: string;

  constructor(name : string, surname : string) { 
    this.name = name;
    this.surname = surname;
  }
}
function logClass(target: any) {

  // save a reference to the original constructor
  var original = target;

  // a utility function to generate instances of a class
  function construct(constructor, args) {
    var c : any = function () {
      return constructor.apply(this, args);
    }
    c.prototype = constructor.prototype;
    return new c();
  }

  // the new constructor behaviour
  var f : any = function (...args) {
    console.log("New: " + original.name); 
    return construct(original, args);
  }

  // copy prototype so intanceof operator still works
  f.prototype = original.prototype;

  // return new constructor (will override original)
  return f;
}

在上面的代码中,新的构造函数添加了一个额外的console.log();。但我也想更改传递给构造函数的参数数量。可能吗?或者我们可以添加任何其他行为吗?如果有,请告诉我?

【问题讨论】:

    标签: typescript


    【解决方案1】:

    您应该能够更改传递给原始构造函数的参数。

    删除参数:

    var f : any = function (...args) {
        const level = args.shift();
        console[level]("New: " + original.name);
        return construct(original, args);
    }
    ...
    new Person("debug", "name", "othername");
    

    添加参数:

    var f : any = function (...args) {
        console.log("New: " + original.name);
        if (args.length == 1) {
            args.push("othername");
        }
        return construct(original, args);
    }
    ...
    new Person("name");
    

    这种方法的问题在于,从构造函数签名中并不清楚实际会发生什么,阅读它的人可能会认为 ctor 接受两个参数,但由于装饰器发生了变化,所以事情会在运行时中断。


    编辑

    不,您不能使用装饰器更改构造函数(或任何方法/函数)的签名,因为它们是静态的并且在编译时会被检查,但装饰器只能在运行时更改。

    我关于为 ctor 添加/删除参数的答案是在运行时完成的,这意味着虽然为 person 声明的 ctor 是:

    constructor(name : string, surname : string)
    

    然后这样做:

    var f : any = function (...args) {
        const level = args.shift();
        console[level]("New: " + original.name);
        return construct(original, args);
    }
    

    创建一个具有以下签名的新 runtime ctor:

    constructor(level: string, name : string, surname : string)
    

    然后(再次在运行时)删除 args 中的第一个元素,将其用作 console 的级别,然后按照预期仅使用两个 args 调用旧 ctor(旧声明签名)。

    【讨论】:

    • 能详细解释一下吗?
    • 我没有做太多,这正是你所做的,我要么从args 数组中删除元素(使用shift),要么向args 添加元素。由于此 args 数组随后用作构造函数参数,因此这样做会按照您的要求更改传递给 ctor 的参数。
    • 没有。它不工作。创建新对象后出现错误。 new Person("debug", "name", "othername");new Person("name"); 这些行是错误行。因为提供的参数与构造函数签名不匹配。
    • 如果我们推送多个元素,即使将元素推送到 args 也将不起作用。
    • 我只想要一件事,那就是类装饰器会改变构造函数的行为。请用你的答案证明它的合理性。
    猜你喜欢
    • 2020-10-25
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多