问题标签 [constructor-chaining]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
398 浏览

syntax - Boo 构造函数链接

在 C# 中,当我想将构造函数链接在一起时,我会这样做......

Boo 中的等效语法是什么?

0 投票
2 回答
467 浏览

c# - 这是使用构造函数链接的好方法还是坏方法?(...允许测试)

我在这里链接我的类构造函数的动机是,我有一个默认构造函数供我的应用程序主流使用,还有一个允许我注入模拟和存根。

在 ":this(...)" 调用和从默认构造函数调用参数化构造函数中的“新”事物看起来有点丑陋,我想知道其他人会在这里做什么?

(仅供参考-> SystemWrapper

0 投票
7 回答
727 浏览

c# - : this() 作为构造函数

我试图更好地理解一般实践......特别是在构造函数中派生 this() 。我知道它的代码较少,但我认为它的可读性较差。这样做是常见的/好的做法吗?还是编写第二个专门处理它的构造函数更好?

或者

任何投入将不胜感激

0 投票
6 回答
4517 浏览

delphi - Delphi:如何隐藏祖先构造函数?

更新:用一个更简单的例子解决了这个问题,最初接受的答案没有回答

给定以下类及其祖先:

现在TCellPhone有 3 个可见的构造函数:

  • 杯子:整数
  • 杯子:整数;茶壶:串
  • 茶壶:string = ''

我该怎么做才能TCellPhone使祖先构造函数(Teapot: string = '')不可见,只留下声明的构造函数:

  • 杯子:整数
  • 杯子:整数;茶壶:串

注意:通常拥有后代构造函数的简单行为会隐藏祖先:

  • 杯子:整数

如果您同时保留祖先构造函数和后代,您可以将后代标记为overload

  • 杯子:整数
  • 茶壶:string = ''

在这个问题的示例代码中,Delphi 弄错了我的overload关键字:

认为:

  • 我想用祖先重载我的构造函数,
  • 当我真的想用兄弟姐妹重载它时

我如何隐藏祖先构造函数?

注意:使用当前定义的 Delphi 语言可能无法隐藏祖先的非虚拟构造函数。“不可能”是一个有效的答案。


尝试回答(失败)

尝试reintroduce用(回退到我随机添加关键字的模式直到它起作用)标记后代构造函数:

但这不起作用,所有三个构造函数仍然可见。:(


原始问题

我有一个对象,该对象来自一个具有构造函数不想看到的类:

注意:这是一个假设的例子。与现实世界一样,在不破坏现有代码的情况下无法更改祖先对象。

现在,当有人使用时,TiPhone我什至不希望他们能够从以下位置看到构造函数TEniac

更糟糕的是:如果他们调用那个构造函数,他们完全想念我的构造函数,以及在这两者之间完成的所有事情。调用错误的构造函数很容易,它们都在 IDE 代码完成中可见,并将编译:

他们得到一个完全无效的对象。

我可以更改TCellPhone为在这些构造函数中引发异常:

但是开发人员不会意识到他们调用了错误的构造函数,直到客户有一天发现错误并对我们处以数十亿美元的罚款。事实上,我试图找到我调用错误构造函数的所有地方 - 但我不知道如何让 Delphi 告诉我!

0 投票
4 回答
19096 浏览

delphi - Delphi:理解构造函数

我想了解

  • 虚拟的
  • 覆盖
  • 超载
  • 重新引入

当应用于对象构造函数时。每次我随机添加关键字直到编译器关闭 - 并且(在使用 Delphi 开发 12 年后)我宁愿知道我在做什么,而不是随机尝试。

给定一组假设的对象:

我希望他们的行为方式从声明中可能很明显,但是:

  • TComputer有简单的构造函数,后代可以覆盖它
  • TCellPhone有一个备用构造函数,后代可以覆盖它
  • TiPhone覆盖两个构造函数,调用每个构造函数的继承版本

现在该代码无法编译。我想了解为什么它不起作用。我也想了解重写构造函数的正确方法。或者也许你永远无法覆盖构造函数?或者也许重写构造函数是完全可以接受的?也许你永远不应该有多个构造函数,也许拥有多个构造函数是完全可以接受的。

我想了解原因。修复它就很明显了。

也可以看看

编辑:我也希望对virtual, override, overload,的顺序进行一些推理reintroduce。因为在尝试所有关键字组合时,组合的数量会爆炸式增长:

  • 虚拟的; 超载;
  • 虚拟的; 覆盖;
  • 覆盖;超载;
  • 覆盖;虚拟的;
  • 虚拟的; 覆盖;超载;
  • 虚拟的; 超载; 覆盖;
  • 超载; 虚拟的; 覆盖;
  • 覆盖;虚拟的; 超载;
  • 覆盖;超载; 虚拟的;
  • 超载; 覆盖;虚拟的;
  • ETC

编辑2:我想我们应该从“给定的对象层次结构是否可能? ”如果不是,为什么不呢?例如,拥有来自祖先的构造函数是根本不正确的吗?

我希望TCellPhone现在有两个构造函数。但我无法在 Delphi 中找到关键字组合,使其认为这是一件有效的事情。我认为我可以在这里有两个构造函数从根本上是错误的TCellPhone吗?


注意:这条线以下的所有内容并不是回答问题所必需的——但它确实有助于解释我的想法。也许您可以根据我的思维过程看到,我遗漏了哪些让一切变得清晰的基本部分。

现在这些声明无法编译:


所以首先我会尝试修复TCellPhone。我将从随机添加overload关键字开始(我知道我不想要reintroduce,因为这会隐藏另一个我不想要的构造函数):

但这失败了:Field definition not allowed after methods or properties.

我从经验中知道,即使我在方法或属性之后没有字段,如果我颠倒virtualandoverload关键字的顺序:Delphi 会闭嘴:

但我仍然得到错误:

方法“创建”隐藏基本类型“TComputer”的虚拟方法

所以我尝试删除这两个关键字:

但我仍然得到错误:

方法“创建”隐藏基本类型“TComputer”的虚拟方法

所以我辞职现在尝试reintroduce

现在 TCellPhone 编译了,但它让 TiPhone 的情况变得更糟:

两者都抱怨我无法覆盖它们,所以我删除了override关键字:

但是现在第二次创建说它必须标记为重载,我这样做(实际上我会将两者都标记为重载,因为我知道如果我不这样做会发生什么):

该部分的一切都很好interface。不幸的是,我的实现不起作用。我的 TiPhone 单参数构造函数不能调用继承的构造函数:

0 投票
4 回答
2893 浏览

delphi - Delphi:如何为后代添加不同的构造函数?

更新:我最初的例子有点复杂。这是一个简单的 8 行示例,它在一个代码块中解释了所有内容。以下不编译给出警告:

注意:这个问题是我正在进行的关于 Delphi 构造函数的微妙之处的系列问题的第 3 部分

原始问题

如何将构造函数添加到现有类?

让我们举一个假设的例子(即我在 SO 编辑器中输入的例子,所以它可能编译也可能不编译):

进一步假设正常使用TXHTMLStream涉及执行大量重复代码后才能使用:

假设我想创建一个简化所有样板设置代码的构造函数:

这将对象的使用简化为:

除了现在 Delphi 抱怨我的新构造函数隐藏了旧构造函数。

方法“创建”隐藏基本类型“TXMLStream”的虚拟方法

我当然不是有意隐藏祖先的创造——我想要两者。

如何将构造函数(具有不同的签名)添加到后代类,同时保留祖先构造函数以便它仍然可以使用?

0 投票
4 回答
3918 浏览

delphi - Delphi:什么时候重新引入隐藏祖先,什么时候显示它们?

今天最近在 Stackoverflow 上我了解到:

我一直在努力理解这一切,所以这是另一个非常具体的问题,支持我处理构造函数的主要问题


更新:替换了整个问题:

构造 TCellPhone 时,可以使用 3 个构造函数:

  • 杯子:整数
  • 杯子:整数;茶壶:串
  • [茶壶:字符串='']

问:为什么constructor(Teapot: string='')不被隐藏?


现在我添加了第三个后代:

构造TiPhone 四个构造函数时可用:

  • 杯子:整数
  • 杯子:整数
  • 杯子:整数;茶壶:串
  • [茶壶:字符串='']

为什么有四个构造函数?我覆盖了现有的三个之一。编辑:这可能是代码洞察力中的一个错误,它向我展示了四个 - 但是当两个相同时我怎么可能调用。


再次使用原始代码:

已知TCellPhone有三个构造函数:

  • 杯子:整数
  • 杯子:整数;茶壶:串
  • [茶壶:字符串='']

如何更改声明TCellPhone以隐藏祖先构造函数?例如,这样:

将只有两个构造函数:

  • 杯子:整数
  • 杯子:整数;茶壶:串

现在用于reintroduce隐藏非虚拟祖先的情况。在前一种情况下TiPhone,有四个构造函数(理想情况下只有两个 - 以TComputer某种方式隐藏其祖先)。但即使我无法修复TComputer,我也可以TiPhone改为只有一个:

现在TiPhone只有一个构造函数:

  • 杯子:整数

Reintroduce 通常只用于抑制隐藏虚拟祖先的警告。在这种情况下:

不是虚拟的——但我仍然可以使用 reintroduce 来隐藏它。


但是现在,如果我添加另一个重载到TiPhone

然后突然(以前隐藏的)祖先回来了:

  • TiPhone.创建(7);
  • TiPhone.Create('粉红色');
  • TiPhone.Create(7, '粉红色');
  • TiPhone.Create();

如您所见,我正在努力理解

  • 当某事被隐藏时
  • 如何隐藏某事
  • 当显示某些东西时
  • 如何显示某事
0 投票
1 回答
2158 浏览

delphi - Delphi:重写的虚拟构造函数后代未被重载调用

我关于 Delphi 构造函数的系列问题中的另一个问题。

我有一个具有虚拟构造函数的基类:

构造函数在有人需要调用的时候是虚拟的

构造函数overridden在后代中:

WhereTCellPhoneTiPhone后代每个都有机会进行自己的初始化(为了便于阅读,不包括成员)。

但是现在我向某个祖先添加了一个重载的构造函数:

TCellPhone 中的备用构造函数调用另一个虚拟构造函数,因此它始终获得正确的覆盖行为:

问题是永远不会调用后代的、被覆盖的构造函数。调用的实际堆栈跟踪链是:

对 的同级调用TCellPhone.Create(int),它是虚拟的,应该在 中调用后代的、被覆盖的方法TiPhone

所以似乎使用兄弟虚拟构造函数的尝试是 Delphi 不能按预期工作。

那么一个构造函数使用另一个构造函数是不是一个坏主意?重载构造函数中的代码是彼此复制粘贴版本的设计意图吗?

我注意到在 .NET 中,一些构造函数相互链接:

这似乎只是一个问题,如果:

  • 构造函数是虚拟的
  • 你重载了构造函数

规则是不能让一个构造函数重载另一个构造函数吗?

0 投票
3 回答
368 浏览

delphi - 了解构造函数可见性

这是两个简单的类,最初都没有关键字(virtual、overload、override、reintroduce):

我将把上述这些定义表示为略短:

并且在构造时TCellPhone只有一个构造函数 ( int, string) - 因为祖先构造函数已被隐藏。我将指出以下的可见构造函数TCellPhone

  • 茶壶:整数;句柄:字符串

现在对于这个问题,前 3 种情况是有道理的,第 4 种情况没有:

1.祖先构造函数被后代隐藏:

  • Teapot: Integer; Handle: string

这是有道理的,祖先构造函数是隐藏的,因为我已经声明了一个新的构造函数。

2.祖先虚构造函数被后代隐藏:

  • Teapot: Integer; Handle: string

这是有道理的,祖先构造函数是隐藏的,因为我已经声明了一个新的构造函数。

注意:因为祖先是虚拟的:Delphi 会警告你隐藏了虚拟祖先(在前面的隐藏静态构造函数的例子中:没人关心,所以没有警告)。可以通过添加reintroduce来抑制警告(意思是“是的,是的,我正在隐藏一个虚拟构造函数。我 打算这样做。”):

3. 由于重载,祖先构造函数没有隐藏在后代中:

  • Teapot: Integer; Handle: string
  • Teapot: Integer

这是有道理的,因为后代构造函数是祖先的重载,所以两者都被允许存在。祖先构造函数没有被隐藏。

4.虚拟祖先构造函数没有隐藏在后代中,因为重载 -但仍然收到警告

这是没有意义的情况:

  • Teapot: Integer; Handle: string
  • Teapot: Integer

    方法“创建”隐藏基本类型“TComputer”的虚拟方法

这没什么意义。不仅祖先隐藏,后代超载;它甚至不应该抱怨。

是什么赋予了?

0 投票
2 回答
622 浏览

javascript - JavaScript 中的链式构造函数

我正在尝试在 JavaScript 中实现某种类层次结构。我想我理解了原型链,但我仍然需要理清构造函数链。按照大卫弗拉纳根的权威指南,我写了

哪里BaseClass()是我用 C++ 编写的本机函数(我正在使用QtScript)。我的问题是,然后,BaseClass()它被称为函数,而不是构造函数。

我可以编写代码BaseClass()以始终充当构造函数,但是它被调用了。但我担心有一天我的一个用户可能会忘记new 并只是写

在这种情况下,我BaseClass()想做一些比初始化全局对象更明智的事情。例如:

但是随后构造函数链接失败!

有没有办法可以链接构造函数并BaseClass() 实际上被称为构造函数?还是我应该教育我的用户永远不要忘记new?现在我很想通过以下方式替换上面的测试:

但我想知道是否有更清洁的方法来处理这个问题。

谢谢!