更新:我最初的例子有点复杂.这是一个简单的8行示例,它解释了一个代码块中的所有内容.以下不编译会发出警告:
TComputer = class(TObject)
public
constructor Create(Cup: Integer); virtual;
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer; Teapot: string); virtual;
end;
Run Code Online (Sandbox Code Playgroud)
注意:这个问题是我正在进行的关于Delphi中构造函数的子句的系列问题的第3部分
如何将构造函数添加到现有类?
让我们给出一个假设的例子(即我在SO编辑器中输入的一个例子,它可能编译也可能不编译):
TXHTMLStream = class(TXMLStream)
public
...
end;
Run Code Online (Sandbox Code Playgroud)
进一步假设正常使用TXHTMLStream涉及在可以使用之前执行大量重复代码:
var
xs: TXHTMLStream;
begin
xs := TXHTMLStream.Create(filename);
xs.Encoding := UTF32;
xs.XmlVersion := 1.1;
xs.DocType := 'strict';
xs.PreserveWhitespace := 'true';
...
xs.Save(xhtmlDocument);
Run Code Online (Sandbox Code Playgroud)
假设我想创建一个简化所有样板设置代码的构造函数:
TXHTMLStream = class(TXMLStream)
public
constructor Create(filename: string; Encoding: TEncoding); virtual;
end;
constructor TXHTMLStream.Create(filename: string; Encoding: TEncoding);
begin
inherited Create(filename);
xs.Encoding …Run Code Online (Sandbox Code Playgroud) 在我开始使用代码约定之前,有时在使用构造函数链时会遇到与参数验证相关的繁琐.
这是一个(人为的)示例最简单的解释:
class Test
{
public Test(int i)
{
if (i == 0)
throw new ArgumentOutOfRangeException("i", i, "i can't be 0");
}
public Test(string s): this(int.Parse(s))
{
if (s == null)
throw new ArgumentNullException("s");
}
}
Run Code Online (Sandbox Code Playgroud)
我希望Test(string)构造函数链接Test(int)构造函数,并使用int.Parse().
当然,int.Parse()不喜欢有一个null参数,所以如果s为null,它将在我到达验证行之前抛出:
if (s == null)
throw new ArgumentNullException("s");
Run Code Online (Sandbox Code Playgroud)
这使得检查毫无用处.
如何解决?好吧,我有时习惯这样做:
class Test
{
public Test(int i)
{
if (i == 0)
throw new ArgumentOutOfRangeException("i", i, "i can't be 0");
}
public Test(string s): …Run Code Online (Sandbox Code Playgroud) 我在这里链接我的类构造函数的动机是,我有一个默认构造函数供我的应用程序主流使用,第二个允许我注入一个mock和一个stub.
在":this(...)"调用中看起来有点丑陋的"新"事物并且反直觉地从默认构造函数中调用参数化构造函数,我想知道其他人会在这做什么?
(仅供参考 - > SystemWrapper)
using SystemWrapper;
public class MyDirectoryWorker{
// SystemWrapper interface allows for stub of sealed .Net class.
private IDirectoryInfoWrap dirInf;
private FileSystemWatcher watcher;
public MyDirectoryWorker()
: this(
new DirectoryInfoWrap(new DirectoryInfo(MyDirPath)),
new FileSystemWatcher()) { }
public MyDirectoryWorker(IDirectoryInfoWrap dirInf, FileSystemWatcher watcher)
{
this.dirInf = dirInf;
if(!dirInf.Exists){
dirInf.Create();
}
this.watcher = watcher;
watcher.Path = dirInf.FullName;
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Created += new FileSystemEventHandler(watcher_Created);
watcher.Deleted += new FileSystemEventHandler(watcher_Deleted);
watcher.Renamed += new RenamedEventHandler(watcher_Renamed);
watcher.EnableRaisingEvents = true;
}
public static string MyDirPath{get{return …Run Code Online (Sandbox Code Playgroud) 今天最近在Stackoverflow上我了解到:
我一直试图弄清楚这一切,所以这是另一个非常具体的问题,支持我处理构造函数的主要问题.
更新:替换了整个问题:
TComputer = class(TObject)
public
constructor Create(Teapot: string='');
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
Run Code Online (Sandbox Code Playgroud)
构建TCellPhone时,可以使用3个构造函数:
问题:为什么constructor(Teapot: string='')不被隐藏?
现在我添加了第三个后代:
TComputer = class(TObject)
public
constructor Create(Teapot: string='');
end;
TCellPhone = class(TComputer)
public
constructor Create(Cup: Integer); overload; virtual;
constructor Create(Cup: Integer; Teapot: string); overload; virtual;
end;
TiPhone = class(TCellPhone)
public
constructor Create(Cup: …Run Code Online (Sandbox Code Playgroud) 这是两个简单的类,最初都没有关键字(虚拟,重载,覆盖,重新引入):
TComputer = class(TObject)
public
constructor Create(Teapot: Integer);
end;
TCellPhone = class(TComputer)
public
constructor Create(Teapot: Integer; Handle: string);
end;
Run Code Online (Sandbox Code Playgroud)
我会将这些以上的定义表示为略短的:
TComputer = class(TObject)
constructor Create(Teapot: Integer);
TCellPhone = class(TComputer)
constructor Create(Teapot: Integer; Handle: string);
Run Code Online (Sandbox Code Playgroud)
构造时TCellPhone只有一个构造函数(int,string) - 因为祖先构造函数已被隐藏.我将指出可见的构造函数TCellPhone:
现在对于这个问题,前3个案例是有意义的,第4个案例没有:
TComputer = class(TObject)
constructor Create(Teapot: Integer);
TCellPhone = class(TComputer)
constructor Create(Teapot: Integer; Handle: string);
Run Code Online (Sandbox Code Playgroud)
Teapot: Integer; Handle: string这是有道理的,祖先构造函数是隐藏的,因为我已经声明了一个新的构造函数.
TComputer = class(TObject)
constructor Create(Teapot: Integer); virtual;
TCellPhone = class(TComputer)
constructor …Run Code Online (Sandbox Code Playgroud) 说我有以下内容:
class Base {
public Base (int n) { }
public Base (Object1 n, Object2 m) { }
}
class Derived : Base {
string S;
public Derived (string s, int n) : base(n) {
S = s;
}
public Derived (string s, Object1 n, Object2 m) : base(n, m) {
S = s; // repeated
}
}
Run Code Online (Sandbox Code Playgroud)
注意我在Derived的两个重载中都需要形式参数n,因此我必须重复这一N = n;行.
现在我知道这可以封装到一个单独的方法中,但是你仍然需要来自两个重载的相同的两个方法调用.那么,是否有一种更"优雅"的方式来做到这一点,也许是通过this结合使用base?
这样我可以有一个私有构造函数接受一个参数s,另外两个重载可以调用那个......或者这可能与拥有一个单独的私有方法相同?
我想知道在C#中链接构造函数时如何更改执行顺序.我见过的唯一方法需要在当前构造函数之外首先调用链式构造函数.
具体来说,请参考以下示例:
public class Foo {
private static Dictionary<string, Thing> ThingCache = new Dictionary<string, Thing>();
private Thing myThing;
public Foo(string name) {
doSomeStuff();
if (ThingCache.ContainsKey(name)) {
myThing = ThingCache[name];
} else {
myThing = ExternalStaticFactory.GetThing(name);
ThingCache.Add(name, myThing);
}
doSomeOtherStuff();
}
public Foo(Thing tmpThing) {
doSomeStuff();
myThing = tmpThing;
doSomeOtherStuff();
}
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,我希望通过这样做来减少代码重复(请注意,我承认在这个人为的示例中,没有保存太多代码,但我正在使用可以获得更多好处的代码.为了清楚起见,我使用此示例):
public class Foo {
private static Dictionary<string, Thing> ThingCache = new Dictionary<string, Thing>();
private Thing myThing;
public Foo(string name) {
if (ThingCache.ContainsKey(name)) {
this(ThingCache[name]);
} else {
this(ExternalStaticFactory.GetThing(name)); …Run Code Online (Sandbox Code Playgroud) 我有一个父类,它有一个重载的构造函数,我有一个子类,它有一个带有可选参数的构造函数.有没有办法让子类的构造函数仍然暴露父类的重载,同时保留它自己的可选参数?
这是两个类及其所需构造函数的一些示例代码:
class Foo {
Foo(String arg0)
{
// do some stuff with arg0
}
Foo(String arg0, List<x> arg1)
: this(arg0)
{
// do some other stuff with arg1 that is special because we have an arg1
}
}
class Bar : Foo {
Bar(String arg0, List<y> arg2 = null, String arg3 = "")
: base(arg0)
{
// some third thing with arg2 and arg3
}
}
Run Code Online (Sandbox Code Playgroud)
这是其他子类构造函数的方法签名我也想要公开父构造函数的重载,但问题是如何做到这一点:
Bar(String arg0, List<x> arg1, List<y> arg2 = null, String arg3 = "") …Run Code Online (Sandbox Code Playgroud) 在反射过程中,是否可以在C#中检查一个构造函数是否调用另一个?
class Test
{
public Test() : this( false ) { }
public Test( bool inner ) { }
}
Run Code Online (Sandbox Code Playgroud)
我想确定每个ConstructorInfo是否在调用链的末尾.
据我所知,Constructctor Chaining就是这样
每当我们创建子类的对象(或调用子类构造函数)时,只有在
我们的子构造函数没有使用此(对于相同的类)或超级关键字调用另一个构造函数时,才会首先自动调用父类的默认构造函数..来源:http://www.java67.com/2012/12/how-constructor-chaining-works-in-java.html
如果我的理解是正确的
然后为以下代码: -
Class First{
First(){
System.out.print("Hello");
}
Class Second extends First{
Second(int i)
{
System.out.println("Blogger");
}
Second(){
this(2); //default constructor is calling another constructor using this keyword
}
public static void main(String[] args)
{
Second ob = new Second();
}
Run Code Online (Sandbox Code Playgroud)
输出应该Blogger只是.
但输出是 HelloBlogger
所以看起来父类的默认构造函数仍然被调用.但引用该来源: -
2)如果你没有从父类或同一个类调用另一个构造函数,而不是Java调用default或没有超类的参数构造函数.
阅读更多:http://www.java67.com/2012/12/how-constructor-chaining-works-in-java.html#ixzz4qztuMrKW
所以请帮忙!
constructor ×7
c# ×6
delphi ×3
delphi-5 ×3
inheritance ×2
cil ×1
java ×1
reflection ×1
subclass ×1
unit-testing ×1