【问题标题】:How to define constructor signature in interface?如何在接口中定义构造函数签名?
【发布时间】:2015-01-05 00:06:17
【问题描述】:

下面是关于在 TypeScript 接口 (Javascript) 中定义构造函数签名的问题,尽管最终它变得不可用。但是,这在 Objective-c 中是可能的,如果在其他地方也能做到这一点,那就太好了。

我有一组数据对象类,它们都将通过一个带有 json 字符串参数的通用构造函数来使用。当我选择 TypeScript 作为一个工具,它有一个编译器,可以帮助我更早地发现错误和问题,我如何在接口中定义一个构造函数,然后在类中实现它?

interface IParsable {

  //constructor(json : string);
  new (json : string);
}

class UserObject implements IParsable {

constructor(json : string) {

   //...
}

代码有效,但编译器显示错误“错误 TS2420:类 'UserObject' 错误地实现了接口 'IParsable'。”如果我在接口中使用“构造函数”而不是 new,那么我会得到“未实现来自接口 IParsable 的方法构造函数”。

更新:在objective-c中,可以使用两种方法创建对象:

第一种方法

UserObject *userObject = [[UserObject alloc] init]; 

对象的创建由两种方法组成。 Alloc - 分配所需的内存,init 是默认的构造函数名称。构造函数就像objective-c中的常规方法一样,并且有它们的名字。因此,如果您需要一个带参数的自定义构造函数,那么您只需定义一个新方法,例如 initWithJson:(NSString *)json。因此,您可以在界面中定义任何您想要的内容并执行合同。

第二种方法

UserObject *userObject = [UserObject new]; 

new 是保留字,但它实际上执行 alloc + init 并且您不能使用自定义构造函数。因此,推荐的方法是使用 alloc + init,这样如果需要,您可以随时将其替换为自定义构造方法,如 alloc + initWithJson。

事实证明,即使在 java 或 C# 中也无法做到这一点。我一直认为这些语言在 OOP 方面更加标准且经过深思熟虑,尽管这件小事在 Objective-c 中做得更好。

【问题讨论】:

  • 接口定义构造函数有什么用?
  • 编译器有什么用?它是一种工具,可帮助您和您的队友更快地发现错误。此外,始终使用接口作为所有实现该接口的类的契约。构造函数只是一个方法,就像所有其他方法一样。在我的所有objective-c项目中,我都能够在接口中定义常见的东西,包括构造函数签名。很奇怪,我需要为这么明显的事情提出论据
  • 我一直在努力解决类似的问题。 TypeScript 手册中的示例不起作用,我猜这是 TypeScript 编译器中的错误。我已经在 github github.com/Microsoft/TypeScript/issues/8917 上创建了一个问题

标签: java c# node.js typescript


【解决方案1】:

extends 子句定义类的实例 的行为,而不是其构造函数。构造函数本身不是类的instance 的一部分。基本上,您是说UserObject实例(在其上调用new 的结果)本身可以调用new,但事实并非如此:

var x = new UserObject();
var y = new x(); // Nonsense, of course

目前 TypeScript 中没有直接的语法来指示构造函数 UserObject 与接口 IParsable 匹配。您可以将其用作解决方法:

class UserObject { ... }
UserObject === <IParsable>undefined;

【讨论】:

    【解决方案2】:

    TypeScript 是结构化类型的,因此您无需在类上实际使用implements 关键字即可获得所需的所有检查。

    在下面的示例中,检查传递给IParsable 的构造函数的参数(在example 函数内)。您也不能将不满足 IParsable 接口的参数传递给 example 函数,即它必须接受字符串参数(或根本不接受参数)。

    我已经突出显示了编译器将捕获的三个错误。

    interface IParsable {
        new (json: string);
    }
    
    class ExampleOne {
        constructor(json: string) {
    
        }
    }
    
    class ExampleTwo {
        constructor(json: string) {
    
        }
    }
    
    class ExampleThree {
        constructor(arg: number) {
    
        }
    }
    
    function example(obj: IParsable) {
        // Error - doesn't pass string arg
        //return new obj();
    
        // Error - wrong argument type
        //return new obj(1);
    
        return new obj('{ a: "b"}');
    
    }
    
    example(ExampleOne);
    example(ExampleTwo);
    
    // Error - Doesn't satisfy IParsable
    //example(ExampleThree);
    

    【讨论】:

    • 我不是很擅长 javascript,因此我想使用 TypeScript,它可以让我使用标准的 OOP 功能并编写经典代码。关于您的示例,您能否对其进行更改,使其看起来更像带有类的常规代码?目前,我不明白为什么示例只是一个普通函数(不是类)以及为什么我们将类名直接传递给示例函数。我正在尝试编写一个代码,在其中定义类及其构造函数,然后使用 new 创建类对象。
    • 该函数只是“编译器如何检查您的类型的示例”。关键概念是您现在在结构类型系统中工作,它与名义类型系统不同。
    猜你喜欢
    • 2018-09-14
    • 1970-01-01
    • 2019-09-11
    • 2012-11-04
    • 1970-01-01
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    相关资源
    最近更新 更多