打字稿中的“静态方面"和“实例方面"究竟是什么? [英] What is exactly the 'static side' and the 'instance side' in typescript?
问题描述
有一个非常相似的问题,但是对于文档中引用的静态端和实例端没有直接的答案.
There is a very similar question, but there is no direct answer to what static side and instance side are referred to in the documentation.
依我的理解,静态部分是一个构造函数,而实例部分是其他一切?
As i vaguely understand, the static side is a constructor and instance side is everything else?
来自打字稿文档的示例:
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);
这个例子中的静态端和实例端是什么?为什么需要使用这样的模式?
What is static side and instance side in this example? Why is a need to use such pattern?
推荐答案
在计算机科学中命名是出了名的困难.
Naming in computer science is notoriously difficult.
在 TypeScript 中,我们通常使用相同的名称来引用类的构造函数(它是运行时存在的值),以及作为实例的类型em> 类(仅在设计时存在,不会发送到 JavaScript).
In TypeScript, we generally use the same name to refer to the constructor of a class (which is a value that exists at runtime), and as the type of the instances of the class (which only exists at design time and is not emitted to JavaScript).
所以在
class Foo { }
const foo: Foo = new Foo();
有一个名为Foo
的类构造器,它可以用来构造我们称之为Foo
的类实例.
there is a class constructor named Foo
, which can be used to construct class instances whose type we call Foo
.
这有点像使用术语乐高";既指制造塑料建筑玩具的公司,也指建筑玩具本身.或者像丰田"作为公司的名称和他们制造的车辆的名称.我们说丰田制造和销售丰田汽车"或乐高制造和销售乐高积木玩具";没有误解,但类似的Foo
构造Foo
实例"可能会令人困惑.就这样吧,我猜.
This is a bit like using the term "Lego" to refer both to the company that manufactures plastic construction toys, and to the construction toys themselves. Or like "Toyota" as the name of a company and the name of the vehicles that they make. We say "Toyota makes and sells Toyota vehicles" or "Lego makes and sells Lego construction toys" without misunderstanding, but the analogous "Foo
constructs Foo
instances" might be confusing. So be it, I guess.
当我们谈论一个类时,我们可能会谈论它的静态方面,它属于构造函数(通常是单数,构造函数",因为有只是其中之一,这对所有实例都是一样的),或者我们可能正在谈论它的实例方面,这与类的实例有关(通常是复数,instances",因为单个构造函数可以创建多个实例,每个实例可能具有与其他实例不同的状态或属性).
When we talk about a class, we might be talking about its static aspects, which pertain to the constructor (generally singular, "the constructor", because there's just one of them, which is the same for all instances), or we might be talking be talking about its instance aspects, which pertain to the instances of the class (generally plural, "instances", because the single constructor can make many instances, each of which has possibly different state or properties from others).
从类型系统的角度来看,类型 Foo
对应于实例侧的形状.要获取静态端的类型,我们可以使用 typeof
类型查询运算符 操作名为 Foo
的构造函数值:typeof Foo
.所以,Foo
是实例端类型,typeof Foo
是静态端类型.
From the type system's standpoint, the type Foo
corresponds to the shape of the instance side. To get the type of the static side, we can use the typeof
type query operator operating on the constructor value named Foo
: typeof Foo
. So, Foo
is the instance side type and typeof Foo
is the static side type.
让我们增加 Foo
来展示它是如何工作的:
Let's augment Foo
to show how this works:
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)
}
}
这是一个单一的类定义,但它有静态端和实例端.Foo
的静态部分,即与它的构造函数有关的东西,包括:
That's a single class definition, but it has a static side and an instance side. The static side of Foo
, that is, things pertaining to its constructor, includes:
- 构造函数本身,其签名为
{new(constructorArgument: string): Foo}
staticProp
属性,其类型为string
,和staticMethod
方法,其签名为{(): void}
.
- the constructor itself, whose signature is
{new(constructorArgument: string): Foo}
- the
staticProp
property, whose type isstring
, and - the
staticMethod
method, whose signature is{(): void}
.
这种类型叫做typeof Foo
,但是如果你愿意,你实际上可以为它定义你自己的接口,就像这样:
This type is called typeof Foo
, but you can actually define your own interface for it if you want, like so:
interface StaticSideOfFoo {
new(constructorArgument: string): Foo;
staticProp: string;
staticMethod(): void;
}
Foo
的实例端,即与其实例相关的东西,包括:
The instance side of Foo
, that is, things pertaining to its instances, includes:
instanceProp
属性,其类型为string
,和instanceMethod
方法,其签名为{(): void}
.
- the
instanceProp
property, whose type isstring
, and - the
instanceMethod
method, whose signature is{(): void}
.
这种类型叫做Foo
,你也可以为此定义你自己的接口:
This type is called Foo
, and you can define your own interface for this also:
interface InstanceSideOfFoo {
instanceProp: string;
instanceMethod(): void;
}
让我们确保我们了解其中的区别:
Let's make sure we understand the difference:
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
请注意,foo1
和 foo2
不能直接访问构造函数签名或 staticProp
或 staticMethod
:
Note that foo1
and foo2
have no direct access to the constructor signature or to staticProp
or staticMethod
:
new foo1("oops"); // error!
foo1.staticProp; // error!
foo1.staticMethod(); // error!
并且 Foo
不能直接访问 instanceProp
或 instanceMethod
:
and that Foo
has no direct access to instanceProp
or instanceMethod
:
Foo.instanceProp; // error!
Foo.instanceMethod(); // error!
foo1
和 foo2
的类型为 Foo
,类似于 InstanceSideOfFoo
,而值Foo
的类型为 typeof Foo
,类似于 StaticSideOfFoo
.我们可以在这里验证:
And the values foo1
and foo2
have type Foo
, which is similar to InstanceSideOfFoo
, whereas the value Foo
has type typeof Foo
, which is similar to StaticSideOfFoo
. We can verify that here:
const instanceSideOfFoo: InstanceSideOfFoo = foo1; // okay
const instanceSideOfFooOops: InstanceSideOfFoo = Foo; // error!
const staticSideOfFoo: StaticSideOfFoo = Foo; // okay
const staticSideOfFooOops: StaticSideOfFoo = foo1; // error!
能够谈论这些不同的方面很有帮助,因为它们具有不同的形状和不同的用途.如果你想做一个接受 Foo
构造函数的函数,你想谈谈 typeof Foo
或 StaticSideOfFoo
或 new (x:string)=>Foo
,而如果你想制作一个接受 Foo
实例的函数,你想谈论 Foo
或 >InstanceSideOfFoo
或 {instanceProp: string}
等
It helps to be able to talk about these different sides because they have different shapes and different uses. If you want to make a function that accepts the Foo
constructor, you want to talk about typeof Foo
or StaticSideOfFoo
or new (x: string)=>Foo
, whereas if you want to make a function that accepts an instance of Foo
, you want to talk about Foo
or InstanceSideOfFoo
or {instanceProp: string}
, etc.
如果没有这样的区别,您最终可能会试图为您的孩子购买乐高公司,或者成为 1997 年丰田凯美瑞的股东.或者也许不是,但是 TypeScript 中的类似错误太容易犯了.我能说什么,命名很难.
Without such a distinction you might end up trying to buy the Lego corporation for your children or becoming a shareholder in a 1997 Toyota Camry. Or maybe not, but the analogous mistakes in TypeScript would be too easy to make. What can I say, naming things is tough.
好的,希望有帮助;祝你好运!
Okay, hope that helps; good luck!
这篇关于打字稿中的“静态方面"和“实例方面"究竟是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!