Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.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
TypeScript中的类设计_Typescript - Fatal编程技术网

TypeScript中的类设计

TypeScript中的类设计,typescript,Typescript,考虑到TypeScript不支持具有不同原型的多个构造函数,我正在努力在TypeScript中实现一些类设计。 基本上,我希望使用一个接受一些参数的公共构造函数和一个“内部”构造函数(仅在库中使用)来设计类。公共构造函数将调用内部构造函数。在C#中,它将如下所示: public class Class1 { internal Class1(int id) { } public Class1(string s) : this(s.Length)

考虑到TypeScript不支持具有不同原型的多个构造函数,我正在努力在TypeScript中实现一些类设计。 基本上,我希望使用一个接受一些参数的公共构造函数和一个“内部”构造函数(仅在库中使用)来设计类。公共构造函数将调用内部构造函数。在C#中,它将如下所示:

public class Class1
{
    internal Class1(int id)
    { 
    }

    public Class1(string s)
        : this(s.Length)
    {
    }
}
class Class1 {

    constructor(public id:number) {} // Public, unfortunately.

    static Fabricate(s:string):Class1 {
        return new Class1(s.length);
    }
}

var classA:Class1 = new Class1(1);
var classB:Class1 = Class1.Fabricate("Hello");

console.log(classA.id);   // "1"
console.log(classB.id);   // "5"
class Class1 {

    id:number;

    private static fabricate(n:number):Class1 {
        var class1:Class1 = new Class1();
        class1.id = n;
        return class1;
    }

    static Fabricate(s:string):Class1 {
        return fabricate(s.length);
    }
}

var classA:Class1 = Class1.Fabricate("Hello");

console.log(classA.id);   // "5"
你知道我怎么把它翻译成打字稿吗


提前谢谢

我的第一个想法是使用重载,但这并不能保护数值构造函数,这还意味着在构造函数中添加一个条件,以确定传递了哪个参数:

class MyClass {
    constructor(s: number);
    constructor(s: string);
    constructor(s: any) {

    }
}
因此,务实的解决方案是拥有一个私人功能:

class MyClass {
    constructor(s: string) {
        this.initialize(s.length);
    }

    private initialize(id: number) {

    }
}

这也适用,并且可能更接近原始版本:

class Class1 {

    id:number;

    constructor(s: string) {
        (n:number) => {
            this.id = n;
        }(s.length)
    }
}

var t:Class1 = new Class1("HELLO");
console.log("Class1ID: " + t.id); // Output = Class1 ID: 5
以下是输出JS供参考:

var Class1 = (function () {
    function Class1(s) {
        var _this = this;
        (function (n) {
            _this.id = n;
        })(s.length);
    }
    return Class1;
})();
var t = new Class1("HELLO");
console.log("Class1 ID: " + t.id);
更新

如果您必须能够使用一个ID调用构造函数,那么我认为您必须使用工厂方法,正如Steve所建议的那样。而且,由于我不认为TS构造函数可以是私有的,如果您需要该方法是私有的,那么您必须完全取消构造函数,并使用一对工厂方法。第一个实例可能如下所示:

public class Class1
{
    internal Class1(int id)
    { 
    }

    public Class1(string s)
        : this(s.Length)
    {
    }
}
class Class1 {

    constructor(public id:number) {} // Public, unfortunately.

    static Fabricate(s:string):Class1 {
        return new Class1(s.length);
    }
}

var classA:Class1 = new Class1(1);
var classB:Class1 = Class1.Fabricate("Hello");

console.log(classA.id);   // "1"
console.log(classB.id);   // "5"
class Class1 {

    id:number;

    private static fabricate(n:number):Class1 {
        var class1:Class1 = new Class1();
        class1.id = n;
        return class1;
    }

    static Fabricate(s:string):Class1 {
        return fabricate(s.length);
    }
}

var classA:Class1 = Class1.Fabricate("Hello");

console.log(classA.id);   // "5"
第二个是这样的:

public class Class1
{
    internal Class1(int id)
    { 
    }

    public Class1(string s)
        : this(s.Length)
    {
    }
}
class Class1 {

    constructor(public id:number) {} // Public, unfortunately.

    static Fabricate(s:string):Class1 {
        return new Class1(s.length);
    }
}

var classA:Class1 = new Class1(1);
var classB:Class1 = Class1.Fabricate("Hello");

console.log(classA.id);   // "1"
console.log(classB.id);   // "5"
class Class1 {

    id:number;

    private static fabricate(n:number):Class1 {
        var class1:Class1 = new Class1();
        class1.id = n;
        return class1;
    }

    static Fabricate(s:string):Class1 {
        return fabricate(s.length);
    }
}

var classA:Class1 = Class1.Fabricate("Hello");

console.log(classA.id);   // "5"

使用TypeScript 1.4,现在可以使用联合类型来允许函数类型重载。请参见中的描述。这应该允许您使用一个构造函数拥有多个构造函数输入类型

联合类型 JavaScript函数可能采用多种可能的参数类型。到目前为止,我们已经使用函数重载支持了这一点。从TypeScript 1.4开始,我们对该功能进行了推广,现在允许您指定值是使用联合类型的多种不同类型之一:

一旦拥有联合类型的值,就可以使用typeof和instanceof检查以类型安全的方式使用该值。您会注意到,我们在上面的示例中使用了这一点,并且可以将x视为if块内部的数字类型

联合类型是一种新类型,可在指定的任何位置工作 类型


谢谢你的回复。但是您的解决方案不允许在不通过公共构造函数的情况下直接调用私有(实际上是内部)构造函数(这是我应该提到的要求)。您可以添加一个私有静态方法,该方法将返回一个新实例。此静态方法是否可以在不使用字符串参数调用构造函数的情况下实例化该类?@ThomasWeiss-否,构造函数将始终被调用。实际上,TS类型安全性不允许您创建
new Class1()公平地说,它需要是
新的Class1(“某些字符串”)
+1,因为我认为我的答案不一定是更好的答案。由于JavaScript中构造函数的工作方式,你不能在TypeScript中真正创建内部/私有构造函数。你能多谈谈你的用例吗?在包含模块上有一个公开的
接口
和工厂方法是可以接受的解决方案吗?我确实应该解释我的用例。我正在尝试将AS3API从SWF连接到JS。因此,我在JS中复制AS3类层次结构,每个类需要两个构造函数:-一个与AS3对应的类具有相同的签名,将被称为客户机代码;这将实例化AS3类并在JS对象中存储一个ID以供将来参考,-当我需要为现有AS3对象返回一个JS对象时,该ID将作为参数(例如,当您获得一个本身是对象的类属性->未由用户实例化,但已存在于AS3中)那么,您是作为中介编写TypeScript代码,还是只需要现有API的定义就可以从TypeScript调用它?TypeScript代码将是愿意访问SWF功能的客户端JS代码的中介。这种方法很有趣,但您不能仅通过传递id来实例化类。不,这是真的-我只是在添加了这个答案后才看到你在上面史蒂夫的帖子上的评论。这确实给了你问题的另一半:一个私有构造函数,当(但仅当)父构造函数被调用时自动调用。考虑到TypeScript的限制,我接受了你的答案,因为这可能是最接近我想要实现的。无论如何,感谢大家,这非常有帮助。只需补充一点,虽然不能将构造函数设为私有,但仍然可以通过让构造函数接受不可见类型的参数来避免错误地使用构造函数。例如,如果您声明了一个不导出的接口,并让公共构造函数接受该接口的单个参数,那么很明显不使用它,如果您尝试,typescript将给出错误。显然,可以绕过它(例如使用{}),您可以在构造函数内检查并抛出异常,但结果仍然非常相似:一个可见但不可用的构造函数。