Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typescript/9.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示例 class Animal { public name: string; constructor() { console.log(this.name); } } class Snake extends Animal { public name = 'BeatSSS'; } let someSnake = new Snake(); 当然,console.log()。预计会出现BeatSSS 如何使用子属性从父

假设下面的Typescript示例

class Animal {
    public name: string;

    constructor() {
        console.log(this.name);
    }
}

class Snake extends Animal {
    public name = 'BeatSSS';
}

let someSnake = new Snake();
当然,
console.log()。预计会出现
BeatSSS

如何使用子属性从父级
构造函数()
执行操作

实际想法:

  • 对child construct()的super()调用解决了这个问题,但我需要对每个孩子都这样做。不是很优雅的解决方案
  • 在父构造上使用超时会记录正确的值,但不可能立即使用类的实例(因为尚未执行超时)

如果您在每个子类上都需要这个,那么应该将name参数传递到父类的构造函数中。

调用super有什么不好的地方?你用其他语言做,用typescript做有什么不对

您正在设置正确运行的类固有的属性。通过构造函数设置这些属性

abstract class Animal {
    constructor(public name: string) {
    }
}

class Snake extends Animal {
    constructor(name: string = 'BeatSSS') {
        super(name);
    }
}

let someSnake = new Snake();         // use the default name 'BeatSSS'
let anotherSnake = new Snake('Foo'); // use a different name

class Dog extends Animal {
    constructor(name: string = 'Rover') {
        super(name);
    }
}

let someDog = new Dog();
let anotherDog = new Dog('Bar');

我喜欢杰夫和邓肯已经提出的很多建议。不过,让我再展示一个选项

abstract class Animal {
    constructor(public name: string) {
        console.log(this.name);
    }
}

class Snake extends Animal { }

let someSnake = new Snake("Snakeeeey!");

注意这里的一些事情

  • Animal
    类似乎确实是一个抽象概念。您可以选择将其标记为
    抽象
    或将其定义为
    接口
    ,但后者不允许您有任何实现(包括构造函数)
  • TypeScript允许我们定义从构造函数初始化的字段。对于公共属性,我们只需编写
    构造函数(公共名称:string)
  • Snake
    类没有显式定义构造函数。尽管如此,在创建snake对象时,使用者必须提供
    Animal
    类所需的
    name
    参数

    在Jeff的代码中,Snake类有一个
    name
    的默认值,该值由
    构造函数(name:string='BeatSSS'){super(name);}
    实现。我不知道你的具体用例。如果snake没有任何有意义的默认名称,我将避免声明这样的构造函数

  • Duncan正确地解释了调用
    super()。此外,这是必要的

    当通过构造函数创建
    Snake
    类型的对象时,父(
    Animal
    的)构造函数必须首先完成。因此,
    Animal
    构造函数无法“查看”子(
    Snake
    的)构造函数中发生的字段初始化的效果。由于构造函数调用的顺序,这是不可能的

    因此,子类型传递父构造函数信息的唯一选项是直接调用
    super(…)


super()。不是很优雅的解决方案

答案基本上是不完全定义子构造函数。如果您的子类必须具有构造函数,则它们将强制您调用
super()
as

在父构造上使用超时会记录正确的值,但不可能立即使用类的实例(因为尚未执行超时)

这是一个非常糟糕的选择。首先,通常不建议在构造函数中进行任何异步代码调用

abstract class Animal {
    constructor(public name: string) {
    }
}

class Snake extends Animal {
    constructor(name: string = 'BeatSSS') {
        super(name);
    }
}

let someSnake = new Snake();         // use the default name 'BeatSSS'
let anotherSnake = new Snake('Foo'); // use a different name

class Dog extends Animal {
    constructor(name: string = 'Rover') {
        super(name);
    }
}

let someDog = new Dog();
let anotherDog = new Dog('Bar');
其次,如果您仍然在
Animal
构造函数中执行
setTimeout(()=>this.fixMyState(),0)
,则会产生不良影响:在对象构造之后,对象立即处于不良状态。如果某个代码立即使用该对象怎么办?
()=>this.fixMyState(),0
甚至没有机会运行来修复对象。经验法则是,在构建对象后立即使其处于良好状态。否则,构造函数应该抛出一个错误,这样就不会有代码试图在错误状态下对对象进行操作。

在父构造函数中获取子值的一种常见方法是使用
setTimeout()
而不使用
delay
属性

使用yout示例,代码如下所示:

类动物{
公共名称:字符串;
构造函数(){
setTimeout(()=>console.log(this.name));
}
}
蛇类动物{
公共名称='BeatSSS';
}
让某条蛇=新蛇();
它为什么有效

因为传递给
setTimeout
的函数将在清除当前调用堆栈后运行。
此时,将完成子属性值的赋值,因此您可以从父属性访问此值

但要小心

在清除当前调用堆栈之前,该值将保持未定义状态。这意味着,例如,如果使用该值初始化父对象中的对象,则在调用堆栈结束之前,该对象将无法正确初始化

以下示例说明了该问题:

类动物{
公共名称:字符串;
公共名称\u副本:字符串;
构造函数(){
设置超时(()=>{
this.name\u copy=名称;
console.log('assigningname\u copy-->',this.name\u copy);
});
}
}
蛇类动物{
公共名称='BeatSSS';
}
让某条蛇=新蛇();
log('child name\u copy-->',someSnake.name\u copy);
此脚本将打印出:

child name_copy ---> **undefined**
assigning name_copy ---> **BeatSSS**


调用父构造函数时,对象尚未完全形成。它只是父部分。这就是几乎所有OOP语言的工作原理。