打字稿中的“静态方面"和“实例方面"究竟是什么? [英] What is exactly the 'static side' and the 'instance side' in typescript?

查看:25
本文介绍了打字稿中的“静态方面"和“实例方面"究竟是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个非常相似的问题,但是对于文档中引用的静态端实例端没有直接的答案.

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 is string, 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 is string, 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

请注意,foo1foo2 不能直接访问构造函数签名或 staticPropstaticMethod:

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 不能直接访问 instancePropinstanceMethod:

and that Foo has no direct access to instanceProp or instanceMethod:

Foo.instanceProp; // error!
Foo.instanceMethod(); // error!

foo1foo2 的类型为 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 FooStaticSideOfFoonew (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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆