我有时会在C#代码中看到:
正在创建的实例,然后调用与该类型的构造函数不同的构造函数。
例如:
Person somebody = new Member();
这会出现哪些可能的情况,为什么会这样?
(我认为这与调用基类构造函数有关,但我无法编译)
答案 0 :(得分:3)
成员继承自Person或Person是一个命名不佳的接口,而Member会实现它:
有关继承的更多信息: http://msdn.microsoft.com/en-gb/library/ms173149(v=vs.80).aspx http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)
有关接口的更多信息: http://msdn.microsoft.com/en-us/library/ms173156.aspx http://en.wikipedia.org/wiki/Protocol_(object-oriented_programming)
您可以使用继承来定义以下内容:
public class Person
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class Adult : Person
{
public string Workplace { get; set; }
}
public class Child : Person
{
public List<string> Toys { get; set; }
}
然后,如果您创建Adult(Adult a = new Adult();
)实例,您将可以访问Name,DateOfBirth和Workplace属性。与孩子一样,您将拥有玩具属性。
此外,您可以存储包含成人和儿童的人员列表:
List<Person> people = new List<Person>();
people.Add(new Adult() { Name = "Adult", DateOfBirth = DateTime.Now, Workplace = "Microsoft" });
people.Add(new Child() { Name = "Child", DateOfBirth = DateTime.Now, Toys = new List<string> { "Car", "Train" } });
然后你可以通过每个印刷出名称和出生日期:
foreach(Person p in people)
{
Console.WriteLine(p.Name + ", " + p.DateOfBirth.ToString("dd/MMM/yy"));
if(p is Child)
{
Console.WriteLine(p.Name + " has the following toys: " + string.Join(", ", ((Child)p).Toys));
}
else if(p is Adult)
{
Console.WriteLine(p.Name + " works at " + ((Adult)p).Workplace;
}
}
接口基本上定义了一个契约(即实现IPerson
的对象将为其方法提供实现)。它就像一个以太网卡:它们如何与网络通信有一个标准,但它们如何在内部工作取决于制造商,只要它们提供预期的行为即可。接口不能包含任何逻辑或存储任何数据,它们只是宣传实现该接口的内容。
public interface IPerson
{
string Name { get; set; }
DateTime DateOfBirth { get; set; }
}
public class Adult : IPerson
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public string Workplace { get; set; }
}
public class Child : IPerson
{
public string Name { get; set; }
public DateTime DateOfBirth { get; set; }
public List<string> Toys { get; set; }
}
还有抽象类提供了接口的一些功能,但可以实现一些逻辑。所有这一切中唯一需要注意的是,类只能从单个类派生(即从其继承),尽管该类可以从另一个类继承。但是,您可以实现多个接口。
答案 1 :(得分:2)
如果Person
是基类Member
同样,这也是有效的:
Object o = new Member();
答案 2 :(得分:1)
你的问题不是关于构造函数的问题。这完全是关于隐式转化。在您的声明中:
Person somebody = new Member();
=
运算符的右侧显然具有(编译时)类型Member
。但是变量somebody
具有(编译时)类型Person
。只有存在从Member
到Person
的隐式转换时,这才合法。然后代码真的像Person somebody = (Person)(new Member());
,除了“强制转换”是不可见的。
现在,最常见的隐式转换是从class
到其(直接或间接)基类的引用转换,或者它实现的接口。
隐式转换有一些不同,从struct
或enum
到其基类或接口的装箱转换。
还有一些用户定义的隐式转换,就像一种方法(用implicit operator
编写)。
还有更多隐式转换,例如从值类型V
到Nullable<>
版本,通常写为V?
,但如果Person
则会很奇怪}只是using
的{{1}}别名,所以这个在你的例子中是不现实的。在这个例子中很少相关的另一个是“扩大”转换,例如, Member?
至int
。
阅读C#语言规范,了解有关转换存在的更多信息。
答案 3 :(得分:0)
Member
类可能看起来像这样......
public class Member : Person {}
Member
来自Person
。