【问题标题】:Typescript create object in shorthand constructor打字稿在速记构造函数中创建对象
【发布时间】:2020-09-25 13:02:08
【问题描述】:

我有一个 Foo 和一个 Bar 类:

class Foo {
  
  private name: string;
  private bar: Bar;

  constructor(name: string, bar: Bar) {
    this.name = name;
    this.bar = bar;
  }
}

class Bar {
  private x: number;
  private y: number;

  constructor(x: number, y: number) {
    this.x = x;
    this.y = y;
  }
}

现在使用 Typescript 构造函数简写,我可以将 Foo 写为:

class Foo {
  constructor(private name: string, private bar: Bar) { }
}

但是我想做的不是将Bar 对象传递给Foo 构造函数。而是传入xy 的值,但仍保持使用简写符号来节省我完整写出类的时间。

实际上,可以这样:

class Foo {
  
  private name: string;
  private bar: Bar;

  constructor(name: string, x: number, y: number) {
    this.name = name;
    this.bar = new Bar(x, y);
  }
}

是用速记符号写的吗?

【问题讨论】:

  • 您能否帮助我们了解为什么您希望将xy 值作为单独的参数而不是Bar 对象传递?是不是将Bar的创建封装在Foo构造函数中,而不是在调用代码中创建?
  • 是的,就是这个想法,将创建封装到 'Foo' 中,这样任何其他实例化 'Foo' 的类都不需要知道 'Bar'

标签: typescript


【解决方案1】:

简写符号称为"parameter properties",具体来说只是将构造函数参数复制到同名的类属性。它不适合你用bar 做的事情。您仍然可以使用 name 属性的简写,如下所示:

class Foo {
    private bar: Bar;
    constructor(private name: string, x: number, y: number) {
        this.bar = new Bar(x, y);
    }
}

我建议你这样做。


如果有人以人身伤害威胁我,除非我想出一些方法来为您的bar 场景使用参数属性,我想我可以像这样滥用default parameters

// ☠ DON'T DO THIS ☠
class AbuseFoo {
    constructor(
        private name: string,
        x: number, y: number,
        private bar: Bar = new Bar(x, y)
    ) { }
}

这个“有效”

// ☠ DON'T DO THIS ☠
let f = new AbuseFoo("name", 1, 2);
console.log(JSON.stringify(f)); // {"name":"name","bar":{"x":1,"y":2}}

产生一个包含私有bar 属性的值,其x1y2。但它公开了一个可选的第四个构造函数参数,该参数覆盖了xy 属性:

f = new AbuseFoo("name", 1, 2, new Bar(3, 4)); 
console.log(JSON.stringify(f)); // {"name":"name","bar":{"x":3,"y":4}}

当然,这比在类中声明bar 并以正常方式在构造函数中设置它更丑陋和复杂。因此,除非您有充分的理由这样做(例如,代码混淆竞赛、人身伤害威胁等),否则我会坚持原来的答案:

不,您不能使用参数属性来设置bar。使用速记法。

Playground link to code

【讨论】:

  • 虽然我假设 OP 是完全明智的,并且会听取您使用速记方法的建议 - 让我感到不安的是,认为一些未来的访问者不会那么明智,请跳过阅读重要的位,只是复制粘贴和滥用默认参数:(
  • class Foo { constructor(public name: string, private bar: Bar) { this.bar = new Bar(); }} 怎么样?我知道,这仍然很奇怪,但至少调用者无法覆盖它typescriptlang.org/play?#code/…
  • @JuanMendes 所以你仍然需要通过Barnew Foo() 然后它被覆盖?我不认为这是这里要求的,但我可能是错的。
  • 你推荐的方式很完美!我没有意识到你可以有一些作为参数属性,但不能有其他的。非常感谢
  • @GeoffJames 嗯,有趣的一点。我进行了编辑,试图更明确地表明复制粘贴会变得很糟糕。如果我认为这样的事情会导致失去生命或肢体,我会删除它,但就目前而言,我认为对于假设的未来访问者了解 为什么 默认参数解决方法不好,这很有趣且具有启发性,因为据我所知,他们会自己想出这个主意。
猜你喜欢
  • 2018-06-26
  • 2016-09-14
  • 1970-01-01
  • 2018-10-27
  • 1970-01-01
  • 1970-01-01
  • 2016-07-01
  • 1970-01-01
  • 2017-11-25
相关资源
最近更新 更多