如何告诉inheritance类不调用其基类’无参数构造函数?
我很惊讶地发现,无论何时调用派生类中的任何构造函数,都会调用我的基类的无参数构造函数。 我认为这就是: base()
用于显式调用基础构造函数,如果我想要的话。
在实例化派生类时,如何防止调用基本构造函数?
using System; namespace TestConstru22323 { class Program { static void Main(string[] args) { Customer customer = new Customer("Jim", "Smith"); Customer c = new Customer(); Console.WriteLine(customer.Display()); Console.ReadLine(); } } public class Person { public Person() { Console.WriteLine("I don't always want this constructor to be called. I want to call it explicitly."); } } public class Customer : Person { private string _firstName; private string _lastName; //public Customer(string firstName, string lastName): base() //this explicitly calls base empty constructor public Customer(string firstName, string lastName) //but this calls it anyway, why? { _firstName = firstName; _lastName = lastName; } public string Display() { return String.Format("{0}, {1}", _lastName, _firstName); } } }
唯一的方法是明确告诉它你想要它调用哪个其他基地; 这当然意味着你必须选择一些基本的ctor来打电话。
你根本不能称之为基础ctor – 概念上 ,构建Customer
是通过首先构建一个Person
,然后在它之上进行Customer
特定的构建来完成的。 例如,假设Person
有private
字段 – 如果允许构建Customer
不首先构造Person
那么这些字段将如何被正确构造?
在.NET中,无论您是否调用:base()
,都将调用对象层次结构中的每个对象构造函数。
:base()
如果没有显式调用它,则会隐式调用:base()
。
如果要在父对象上调用不同的构造函数而不是默认构造函数,则可以使用:base()
。
如果你的父构造函数中的代码每次都不应该被调用,那么将代码移动到它自己的方法可能会更好,这个方法需要在构造对象后显式调用。 或者,在父对象上创建参数化构造函数,并使用该参数来确定是否应该执行代码。
例如:
:base(true) - This executes your code. :base(false) - This does not execute your code.
正如其他人所指出的,派生实例必须调用其基类之一的构造函数。
如果要控制基类的初始化逻辑的执行,请删除其默认构造函数并将其替换为如下所示:
public class Base { // Base has no default constructor public Base(bool initialize) { if (initialize) { // ... logic here } } }
派生的构造函数看起来像这样:
// Derived1 executes the initialization logic public Derived1(): base(true) {} // Derived2 does not public Derived2(): base(false) {}
您可以使默认的基础构造函数protected
,然后只为基础及其子项提供非默认的构造函数。
编辑
您可以为基类提供具有不同签名的protected
构造函数(例如受保护的枚举类型),并将初始化代码放在那里,而默认构造函数也protected
,不会进行特定的初始化。
您只需要为某些派生对象调用构造函数的要求不符合面向对象的原则。 如果它是一个人,那么它需要这样构建。
如果需要对某些对象进行共享初始化,则应考虑创建Initialize
方法或添加将由特定派生对象调用的参数化构造函数。
参数化的构造函数方法感觉有点尴尬:
public abstract class Person { protected Person() { } protected Person( bool initialize ) { if (initialize) { Initialize(); } } // ... } public class Customer : Person { public Customer(string firstName, string lastName) { // ... } } public class Employee : Person { public Customer(string firstName, string lastName) : base(true) { // ... } }
实例化类时,inheritance层次结构中的所有类都从最顶层的Parent到最下面的子节点实例化,停止在您实例化的类型上。 因此,如果您实例化System.Text.StringBuilder(),首先调用System.Object的默认构造函数,然后调用StringBuilder()。 您可以使用base关键字来调用不同的构造函数(一个具有相同或更少的参数),但不能使用更多的参数。 如果未指定base,则会调用默认构造函数,因此会发生这种情况。 您还可以在实例方法的上下文中使用base关键字来调用基本实现,例如在装饰器模式的情况下。 如果您不想调用基类私有构造函数,那么您应该使用私有默认构造函数设置子项,并在其他构造函数上显式调用base(params)。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication2 { class ProcessCaller { static void Main() { MyDerived md1 = new MyDerived(1); object o = new System.Text.StringBuilder();//This will implicitly instantiate the classes in the inheritance hierarchy: object, then stringbuilder } } public class MyBase { int num; public MyBase() { Console.WriteLine("in MyBase()"); } public MyBase(int i ) { num = i; Console.WriteLine("in MyBase(int i)"); } public virtual int GetNum() { return num; } } public class MyDerived: MyBase { //set private constructor. base(i) here makes no sense cause you have no params private MyDerived() { } // Without specifying base(i), this constructor would call MyBase.MyBase() public MyDerived(int i) : base(i) { } public override int GetNum() { return base.GetNum();//here we use base within an instance method to call the base class implementation. } } }
一种方法是将您的基本默认构造函数设置为私有,但只有在基类中创建一个帮助器构造函数时才会有效,只有在您明确需要它时才调用私有构造函数。
class Base { private Base() { ... special default base logic ... } protected Base(... params ...) : this() { ... exposed base that calls private cons ... } protected Base(... other params ...) /* no default call */ { ... exposed cons that doesnt call default ...} } class DerivedNoCall { public DerivedNoCall() : base(... other params ...) {} //<-- will NOT call default base } class DerivedDoCall { public DerivedDoCall() : base(... params ...) {} //<-- WILL call default base cons indirectly }
这是非常人为的, @ aakashm有最好的答案。
- 如何区分浏览器的多个选项卡之间的会话
- 在VSIX扩展中使用的WPF-Log4Net在目标VS上安装时没有输出日志
- 如何在devexpress datagrid中包含图像
- 如何使用razor引擎进行图像src的电子邮件模板化
- 路径和字母数字字符的正则表达式
- 如何在SQL Server 2008中将Excel文件插入/检索到varbinary(max)列?
- ASP.NET MVC4:属性参数必须是属性参数类型的常量表达式,typeof表达式或数组创建表达式
- 从powershell-script登录到csharp-program(log4net-logfile)
- 如何通过parallel.foreach了解每个线程产生的threadid