TypeScript - Copy-Constructor(不允许多个构造函数实现)

11 浏览
0 Comments

TypeScript - Copy-Constructor(不允许多个构造函数实现)

TypeScript是否支持复制构造函数(例如C++的示例)?

当答案是否定的(或者说尚未支持)时,那么初始化我们扩展的基类并从现有实例(具有相同基类类型)复制的最佳做法是什么?

我尝试了但是出现了错误:

不允许有多个构造函数实现

当前代码:

目前我们的代码使用了手动声明的基类的copy()方法,该方法需要基类已经初始化,

但是我们的基类(ShopConfig)在其构造函数中有一些相当昂贵的操作,这些操作已经完成了一次,如果TypeScript中有复制构造函数的概念实现,那么这些操作将不再需要。

class ShopConfig {

public apiKey: string;

public products: any;

constructor(apiKey: string = 'trial') {

this.apiKey = apiKey;

//从本地数据库获取产品列表

this.products = expensiveDataBaseQuery();

}

protected copy(other: ShopConfig) {

for (const field in other) {

if (other.hasOwnProperty(field)) {

this[field] = other[field];

}

}

}

}

class ShopManager extends ShopConfig {

constructor(config: ShopConfig) {

super();

super.copy(config);

console.log('ShopManager configurations:', config);

}

}

0
0 Comments

在TypeScript中,没有直接的拷贝构造函数的功能。但是可以通过模拟实现来达到类似的效果。下面给出了一个示例代码:

class A {
   public propertyA: string;
   public propertyB: string;
   private copy(object: A) {
       object.propertyA = this.propertyA;
       object.propertyB = this.propertyB;
   }
   public clone() {
      const obj = new A();
      this.copy(obj);
      return obj;
   }
}

上述代码实现了一个类A,其中包含了一个私有方法`copy`用于复制对象的属性,以及一个公共方法`clone`用于创建并返回一个新的A类实例。

如果构造函数中包含了复杂的逻辑,可以将其移动到另一个函数中,比如命名为`initialize`,然后在构造函数之外调用该函数。可以使用工厂方法模式来避免在创建对象时需要手动调用`initialize`方法,或者可以通过构造函数参数的方式,在`clone`方法内部创建新对象时不调用`initialize`方法。

如果需要频繁进行对象的复制操作(比如实现原型设计模式),建议使用lodash库中的`cloneDeep`方法。

然而,如果需要构造基类或父类的拷贝,上述方法并不能满足要求。将耗时的逻辑移到其他方法中并手动调用会增加出错的可能性,因此不能完全替代基于继承的拷贝构造函数的功能。

总之,TypeScript中没有直接支持拷贝构造函数的功能。在构造函数中应该尽量保持简单,只进行初始属性的赋值。如果需要避免在构造函数中执行耗时的逻辑,可以将其分离到其他对象中,或者使用其他设计模式来解决问题。

需要注意的是,TypeScript允许构造函数和方法接受多个类型的参数,这是语言的基本特性。如果认为这种复杂性违反了某些模式,可以选择不使用TypeScript,或者至少接受它作为语言的一部分(而不是其他开发者的错误)。在整个项目中都需要手动调用分离方法来构造对象,会导致代码更加复杂和难以维护。

如果你认为上述方法过于复杂,你应该知道有些项目的方法可能有1000多行代码,并且我发明了折叠滚动条(github.com/microsoft/vscode/issues/72807),因为在这个行业中,我们更多地处理的是别人的代码,而不是自己的代码。

0
0 Comments

在TypeScript中,不允许有多个构造函数的实现。然而,我们可以通过一些方法来实现类似于复制构造函数的功能。

首先,我们需要修改类的构造函数参数类型,使其同时接受构造函数和复制构造函数的类型。我们可以使用类型的组合来实现,使用`|`操作符连接不同的类型。

然后,在构造函数的实现中,我们需要检查参数的类型。对于类类型的参数,我们可以使用`instanceof`操作符进行检查;对于基本类型的参数,我们可以使用`typeof`操作符进行检查。

最后,根据参数的类型来决定是进行构造还是复制操作,并处理相关的任务(例如,如果是复制构造函数,则进行复制操作)。

以上是实现复制构造函数的一种方法。下面是一个示例代码:

class ShopConfig {
    public apiKey: string;
    public products: any;
    constructor( v: ShopConfig
            | string | String
            | null
            = 'trial'
    ) {
        if ( ! v) {
            throw new Error('ShopConfig: expected API-Key or existing instance');
        } else if (v instanceof ShopConfig) {
            for (const field in v) {
                if (v.hasOwnProperty(field)) {
                    this[field] = v[field];
                }
            }
        } else if (typeof v === 'string' || v instanceof String) {
            this.apiKey = v.toString();
            this.products = expensiveDataBaseQuery();
        }
    }
}
class ShopManager extends ShopConfig {
    constructor(config: ShopConfig) {
        super(config);
        console.log('ShopManager configurations:', config);
    }
}

需要注意的是,上述复制相关的逻辑并不复杂,只有几行代码。如果逻辑更复杂,我们可以在基类中创建一个`_copy(...)`方法(可能使用`protected`修饰符而不是`private`,以便可以被子类覆盖),然后在同一个类的构造函数中调用该方法(在类型检查之后)。

另外,可能需要将`ShopConfig`放在构造函数的类型链的最后,以确保正常构造函数的优先级高于复制构造函数,但我们将其放在第一位是为了确保用户注意到可以进行复制操作。

0