当前位置:  开发笔记 > 编程语言 > 正文

如何继承构造函数?

如何解决《如何继承构造函数?》经验,为你挑选了9个好方法。

想象一下具有许多构造函数和虚方法的基类

public class Foo
{
   ...
   public Foo() {...}
   public Foo(int i) {...}
   ...
   public virtual void SomethingElse() {...}
   ...
}

现在我想创建一个覆盖虚方法的后代类:

public class Bar : Foo 
{
   public override void SomethingElse() {...}
}

而另一个后代做了更多的东西:

public class Bah : Bar
{
   public void DoMoreStuff() {...}
}

我是否真的必须将所有构造函数从Foo复制到Bar和Bah?然后,如果我在Foo中更改构造函数签名,我是否必须在Bar和Bah中更新它?

有没有办法继承构造函数?有没有办法鼓励代码重用?



1> Jeff Yates..:

是的,您必须实现对每个派生有意义的构造函数,然后使用该base关键字将该构造函数指向适当的基类或this关键字,以将构造函数指向同一个类中的另一个构造函数.

如果编译器对继承构造函数做出了假设,那么我们将无法正确确定对象的实例化方式.在大多数情况下,您应该考虑为什么您有这么多构造函数并考虑将它们减少到基类中的一个或两个.然后,派生类可以使用常量值来掩盖其中的一些,null并且仅通过其构造函数公开必要的值.

更新

在C#4中,您可以指定默认参数值并使用命名参数使单个构造函数支持多个参数配置,而不是每个配置都有一个构造函数.


我认为必须复制一个构造函数的签名太多了.在我的实际情况中,我有一个构造函数,我不想复制它.然后我必须在两个地方改变它.
不可见的基类构造函数是C#语言的设计者(很可能是其他CLR语言)做出选择的结果.令人遗憾的是,它与应用程序的前期设计无关,但是语言的局限性使得基类中的许多构造函数的设计(通常)不可行.
对我来说最烦人的是自定义异常 - `Sub New()`,`Sub New(Message As String)`,`Sub New(Message As String,InnerEx as Exception)`,`Sub New(Info As Serialization.SerializationInfo) ,Context As Serialization.StreamingContext)`... Yawn`
在这种情况下,你是对的,尽管现在"最佳实践"成为"最佳实践".

2> Kon..:

387个构造函数?? 那是你的主要问题.相反怎么样?

public Foo(params int[] list) {...}


我想这样可以鼓励人们为提问者没有想到要提出的更高层次的问题提供更好的解决方案,而不是用它来贬低它们.
宾果,人们不尽可能多地使用参数
如果只有一个构造函数,你的答案会改变吗?
说实话,我从来没有在任何生产代码中使用它们.我通常有List 或我传递的一些集合.我渴望利用params的那一天.:)
这实际上只有在参数类型相同时才有效,并用作初始化对象的列表.但是如果构造函数甚至有不同的签名(比如一个需要两个整数,另一个是两个字符串,另一个是int和一个字符串,第四个是浮点数和枚举.你将花费大部分构造函数检查类型和unbox - 在运行时做的事情,应该由编译器完成.

3> James Curran..:

是的,你必须复制所有387个构造函数.您可以通过重定向来重复使用它们:

  public Bar(int i): base(i) {}
  public Bar(int i, int j) : base(i, j) {}

但那是你能做的最好的事情.



4> 小智..:

太糟糕了,我们被迫告诉编译器显而易见:

Subclass(): base() {}
Subclass(int x): base(x) {}
Subclass(int x,y): base(x,y) {}

我只需要在12个子类中做3个构造函数,所以这没什么大不了的,但我不太喜欢在每个子类上重复这个,因为我不习惯这么长时间写它.我确信这是有道理的,但我认为我从未遇到过需要这种限制的问题.


Resharper让这很容易!(Alt + Insert,Constructors)

5> dviljoen..:

不要忘记,您也可以在相同的继承级别将构造函数重定向到其他构造函数:

public Bar(int i, int j) : this(i) { ... }
                            ^^^^^



6> 小智..:

另一个简单的解决方案可能是使用包含参数作为属性的结构或简单数据类; 这样你可以提前设置所有默认值和行为,将"参数类"作为单个构造函数参数传递:

public class FooParams
{
    public int Size...
    protected myCustomStruct _ReasonForLife ...
}
public class Foo
{
    private FooParams _myParams;
    public Foo(FooParams myParams)
    {
          _myParams = myParams;
    }
}

这避免了多个构造函数(有时)的混乱,并提供了强大的类型,默认值以及参数数组未提供的其他好处.它还可以很容易地继续发展,因为从Foo继承的任何内容仍然可以根据需要访问甚至添加到FooParams.你仍然需要复制构造函数,但是你总是(大部分时间)只(作为一般规则)(至少现在)需要一个构造函数.

public class Bar : Foo
{
    public Bar(FooParams myParams) : base(myParams) {}
}

我真的很喜欢重载的Initailize()和类工厂模式方法更好,但有时你只需要一个智能构造函数.只是一个想法.



7> Keith..:

作为Foo一个类,你能不能创建虚拟重载Initialise()方法?那么它们可用于子类并且仍可扩展吗?

public class Foo
{
   ...
   public Foo() {...}

   public virtual void Initialise(int i) {...}
   public virtual void Initialise(int i, int i) {...}
   public virtual void Initialise(int i, int i, int i) {...}
   ... 
   public virtual void Initialise(int i, int i, ..., int i) {...}

   ...

   public virtual void SomethingElse() {...}
   ...
}

除非你有很多默认属性值并且你经常遇到它,否则这应该没有更高的性能成本.



8> Pavlo Neiman..:
public class BaseClass
{
    public BaseClass(params int[] parameters)
    {

    }   
}

public class ChildClass : BaseClass
{
    public ChildClass(params int[] parameters)
        : base(parameters)
    {

    }
}



9> Aaron Murgat..:

我个人认为这在Microsofts部分是一个错误,它们应该允许程序员覆盖基类中的构造函数,方法和属性的可见性,然后使它成为总是继承构造函数.

这样我们只是简单地覆盖(具有较低的可见性 - 即私有)我们不想要的构造函数,而不必添加我们想要的所有构造函数.德尔福这样做,我想念它.

例如,如果要覆盖System.IO.StreamWriter类,则需要将所有7个构造函数添加到新类中,如果您想要注释,则需要使用标题XML对每个构造函数进行注释.更糟糕的是,元数据视图dosnt将XML注释作为正确的XML注释,因此我们必须逐行进行复制并粘贴它们.微软在这里想什么?

我实际上已经编写了一个小实用程序,您可以粘贴元数据代码,并使用过度可见性将其转换为XML注释.


这个问题不是可见性问题.除了从派生类构造函数调用之外,子类构造函数不能用于构建派生类对象.需要什么IMHO是一个工具,通过它,子类可以指定对于所有父类构造函数,编译器应该自动生成具有相同参数的子类构造函数,该构造函数调用适当的父构造函数,然后调用通用子代. - 类构造函数模板.
推荐阅读
围脖上的博博_771
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有