Base Base构造函数C#初始化

时间:2014-06-05 17:55:28

标签: c# inheritance

简化方案。三个分支,GrandParent,父母和孩子。我想要做的是使用GrandParent和Parent构造函数来初始化Child实例。

class GrandParent ()
{
    public int A {get; protected set;}
    public int B {get; protected set;}

    public GrandParent (int a, int b);
    {
        A = a;
        B = b;
    }
}

class Parent : GrandParent ()
{
    public Parent () {}
}

Child Class,问题出现了。

class Child : Parent ()
{
    public int C {get; protected set}

    public Child (int c) // here I want it to also call the GrandParent (int a, int b)
                         // before calling Child (int c)
    {
        C = c;
    }
}

Child = new Child (1,2,3);

我想要的是变量a,b和c分别得到1,2作为值。我知道只需将A = aB = b添加到Child构造函数即可解决此问题。

这可能吗?如果是这样的话?

我开始查看base(),但看起来它只能访问Parent类,而不是GrandParent

提前致谢。

PS。如果之前有人问过,我提前道歉,我什么都没找到。

快速编辑:我正在努力使解决方案尽可能简单,以便进一步发展。

4 个答案:

答案 0 :(得分:4)

您只能将构造函数调用到直接超类。直接超类需要公开您需要的选项。它可以使用protected构造函数安全地执行此操作。

答案 1 :(得分:1)

C#良好实践假定您在每个子进程中调用基类构造函数。也就是说,你将从父母和基地(a,b)调用基地(a,b)来自孩子,这将调用祖父母ctor。这让你无法接受。这是你的代码片段重写:

class GrandParent ()
{
    public int A {get; protected set;}
    public int B {get; protected set;}

    public GrandParent (int a, int b);
    {
        A = a;
        B = b;
    }
}

class Parent : GrandParent ()
{
    public Parent (int a, int b):base(a,b) {}
}
Child Class, were the problem occurs.

class Child : Parent ()
{
    public int C {get; protected set}

    public Child (int a, int b, int c):base(a,b)
    {
        C = c;
    }
}

答案 2 :(得分:1)

您需要将变量通过每个构造函数传递给它的基础构造函数:

class Child : Parent ()
{
    public int C {get; protected set}

    public Child (int a, int b, int c) : base(a,b)
                         // before calling Child (int c)
    {
        C = c;
    }
}

Child = new Child (1,2,3);

class GrandParent ()
{
    public int A {get; protected set;}
    public int B {get; protected set;}

    public GrandParent (int a, int b);
    {
        A = a;
        B = b;
    }
}

class Parent : GrandParent ()
{
    public Parent (int a, int b) : base(a,b) {}
}

答案 3 :(得分:1)

孩子是有限适用性的类比,因为派生类不是基础的“孩子”,因为人或动物的孩子是儿童的它们,甚至作为子目录是树中的目录或从属节点(GUI或数据结构)。

这种关系实际上是对于下位词的上位词。遗憾的是, hypernym 并不像 parent 那样众所周知,因此人们经常使用不太准确的来解释继承而不是上位词

现在,让我们考虑第一类声明:

class GrandParent
{
    public int A {get; protected set;}
    public int B {get; protected set;}

    public GrandParent (int a, int b)
    {
        A = a;
        B = b;
    }
}

这与问题完全相同,只是第一行的错误()和第六行的;已删除。

它有一个构造函数,需要两个整数。

这意味着:

  1. 在没有传递两个整数的情况下创建GrandParent没有逻辑意义。
  2. 这是如何定义的错误。
  3. 好吧,也许不是一个错误,但肯定有点懒。
  4. 当我们来到Parent

    的声明时
    class Parent : GrandParent
    {
        public Parent () {}
    }
    

    这里我修复了语法错误,但没有别的。

    由于构造函数中没有明确使用base,因此隐含调用无参数base()。也就是说,上述内容完全相同:

    class Parent : GrandParent
    {
        public Parent()
            : base()
        {
        }
    }
    

    new Parent()的任何来电都将通过base()来电new GrandParent()。由于GrandParent()上没有无参数构造函数,因此无法编译。

    这里的语言规则正在帮助我们:

    1. 我们说在没有使用两个整数的情况下创建GrandParent是没有意义的。
    2. 我们说Parent是一种GrandParent
    3. 我们说过只创建Parent而没有设置这两个整数。
    4. 我们说过三件事都是真的,但事实并非如此。语言规则是正确的,指出我们的错误。

      要解决此问题,我们需要:

      1. 允许创建GrandParent,而不在其构造中使用这两个整数。
      2. 强制Parent s总是在其构造中使用两个整数,然后依次使用基础构造函数。
      3. Parent调用base(a, b)上的无参数构造函数具有一些设定值。
      4. 做上述的混合物。例如。如果调用无参数构造函数,我们可以调用两个set值,也可以将另一个构造函数传递给基础构造函数。
      5. 上面的第3个看起来像是:

        class Parent : GrandParent
        {
            public Parent()
                : base(42, -343213)
            {
            }
        }
        

        或者其他什么,只要这些数字来自某个地方(显然在真实的代码中,它们会与比我的随机输入更合理的东西相关)。

        现在我们有一个Parent实际上具有逻辑意义,其余的可以遵循。