有一个非常相似的问题,但是文档中提到的静态端和实例端没有直接答案。
正如我依稀理解的那样,静态端是构造函数,实例端是其他一切?
打字稿文档中的一个示例:
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick(): void;
}
function createClock(ctor: ClockConstructor, hour: number, minute: number): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) { }
tick() {
console.log("tick tock");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
Run Code Online (Sandbox Code Playgroud)
什么是静态的侧面和实例方在这个例子吗?为什么需要使用这样的模式?
jca*_*alz 13
计算机科学中的命名是出了名的困难。
在 TypeScript 中,我们通常使用同名来指代类的构造函数(它是一个在运行时存在的值),并作为类的实例的类型(它只在设计时存在,不会发出到JavaScript)。
所以在
class Foo { }
const foo: Foo = new Foo();
Run Code Online (Sandbox Code Playgroud)
有一个名为 的类构造函数Foo,它可以用来构造我们称之为 类型的类实例Foo。
这有点像使用术语“乐高”来指代制造塑料建筑玩具的公司和建筑玩具本身。或者像“Toyota”作为公司名称和他们制造的车辆的名称。我们说“丰田制造并销售丰田汽车”或“乐高制造并销售乐高积木玩具”不会引起误解,但类似的“Foo构造Foo实例”可能会令人困惑。就这样吧,我猜。
当我们谈论一个类,我们可能会谈论它的静态方面,其中涉及到构造(一般奇异“的构造”,因为这里的只是其中之一,这是相同的所有实例),或者我们可能会谈论它的实例方面,它与类的实例有关(通常是复数,“instance s ”,因为单个构造函数可以创建许多实例,每个实例可能具有与其他实例不同的状态或属性)。
从类型系统的角度来看,类型Foo对应于实例侧的形状。要获取静态端的类型,我们可以使用typeof类型查询运算符操作名为Foo: 的构造函数值typeof Foo。所以,Foo是实例端类型,typeof Foo是静态端类型。
让我们扩充Foo以展示它是如何工作的:
class Foo {
instanceProp: string;
constructor(constructorArgument: string) {
this.instanceProp = constructorArgument;
}
instanceMethod(): void {
console.log("Instance method called on " + this.instanceProp)
}
static staticProp: string = "Static Thing";
static staticMethod(): void {
console.log("Static method called on " + this.staticProp)
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个单一的类定义,但它有静态端和实例端。的静态部分Foo,即与其构造函数有关的内容,包括:
{new(constructorArgument: string): Foo}staticProp财产,其类型为string,和staticMethod方法,其签名{(): void}。这种类型被称为typeof Foo,但如果需要,您实际上可以为它定义自己的接口,如下所示:
interface StaticSideOfFoo {
new(constructorArgument: string): Foo;
staticProp: string;
staticMethod(): void;
}
Run Code Online (Sandbox Code Playgroud)
的实例侧Foo,即与其实例相关的事物,包括:
instanceProp财产,其类型为string,和instanceMethod方法,其签名{(): void}。这种类型称为Foo,您也可以为此定义自己的接口:
interface InstanceSideOfFoo {
instanceProp: string;
instanceMethod(): void;
}
Run Code Online (Sandbox Code Playgroud)
让我们确保我们了解差异:
const foo1 = new Foo("Number 1");
console.log(foo1.instanceProp); // Number 1
foo1.instanceMethod(); // Instance method called on Number 1
const foo2 = new Foo("Number 2");
console.log(foo2.instanceProp); // Number 2
foo2.instanceMethod(); // Instance method called on Number 2
console.log(Foo.staticProp); // Static Thing
Foo.staticMethod(); // Static method called on Static Thing
Run Code Online (Sandbox Code Playgroud)
请注意,foo1并foo2不能直接访问构造函数签名或访问staticProp或staticMethod:
new foo1("oops"); // error!
foo1.staticProp; // error!
foo1.staticMethod(); // error!
Run Code Online (Sandbox Code Playgroud)
并且Foo无法直接访问instanceProp或instanceMethod:
Foo.instanceProp; // error!
Foo.instanceMethod(); // error!
Run Code Online (Sandbox Code Playgroud)
并且值foo1和foo2具有类型Foo,类似于InstanceSideOfFoo,而值Foo具有类型typeof Foo,类似于StaticSideOfFoo。我们可以在这里验证:
const instanceSideOfFoo: InstanceSideOfFoo = foo1; // okay
const instanceSideOfFooOops: InstanceSideOfFoo = Foo; // error!
const staticSideOfFoo: StaticSideOfFoo = Foo; // okay
const staticSideOfFooOops: StaticSideOfFoo = foo1; // error!
Run Code Online (Sandbox Code Playgroud)
能够谈论这些不同的方面会有所帮助,因为它们具有不同的形状和不同的用途。如果你想接受的一个函数Foo的构造,你想谈论typeof Foo或StaticSideOfFoo或者new (x: string)=>Foo,而如果你想接受的实例的功能Foo,你想谈论Foo或InstanceSideOfFoo或{instanceProp: string}等
如果没有这样的区别,你最终可能会试图为你的孩子购买乐高公司,或者成为 1997 年丰田凯美瑞的股东。或者也许不是,但是 TypeScript 中的类似错误太容易犯了。我能说什么,命名事情很难。
好的,希望有帮助;祝你好运!
| 归档时间: |
|
| 查看次数: |
661 次 |
| 最近记录: |