带有内部类对象的抽象类构造函数继承

时间:2015-03-25 11:26:21

标签: c# oop inheritance abstract-class

我们说我有一个抽象类A.我在这里有一些内部类:

public abstract class A
{
        public InnerOne x;
        public InnerTwo y;
        public A(){
           this.x = new InnerOne();
           this.y = new InnerTwo();
        }
        public class InnerOne
        {
            public virtual double value(){
                return 0;
            }
        }
        public class InnerTwo
        {
            public virtual double value(){
                return 0;
            }
        }
}

然后我得到了这样的孩子:

 public class B: A
    {
            public B():base(){

            }
            public class InnerOne: A.InnerOne
            {
                 public override virtual double value(){
                    return 100;
                }
            }
            public class InnerTwo: A.InnerTwo
            {
                 public override virtual double value(){
                    return 100;
                }
            }
    }

所以我认为当我调用B构造函数时,我会通过创建它的内部类实例来初始化xy。但实际上它不是那样的。当我像这里调用vaule函数时,它会返回零。

A newobject = new B();
var bv1 = B.x.value();
var bv2 = B.y.value();

是否可以强制B类通过它的内部类对象(而不是来自父抽象类的对象)初始化它的xy字段)没有重写它的构造函数?

4 个答案:

答案 0 :(得分:1)

即使你已经在A或B中定义了类,它们仍然是公共的,它们可以在A或B之外访问。它与在A或B之外定义的类没有什么不同。

想象一下在A类和B类之外定义InnerOneInnerTwo的相同代码。它将具有相同的上述行为。你的混乱根源是对内部阶级使用的误解。

为了获得100,在B内部,您需要使用覆盖这些值的实例显式替换X和Y变量的实例。除非你这样做,否则你不会得到100。

 public class B: A
    {
            public B():base(){
            X = new OverridenInnerOne();
            Y = new OverridenInnerTwo();
            }
            public class OverridenInnerOne: A.InnerOne
            {
                 public override virtual double value(){
                    return 100;
                }
            }
            public class OverridenInnerTwo: A.InnerTwo
            {
                 public override virtual double value(){
                    return 100;
                }
            }
    }

答案 1 :(得分:1)

内心阶层' aspect(嵌入式类定义)只会分散注意力,它不起作用。

并回答这个问题:不,你不能拥有虚拟构造者'这样工作。

当然有很多方法可以将100而不是0作为返回值,但这个问题太过于人为,无法提出问题。

答案 2 :(得分:1)

B.xB.yA.InnerOneA.InnerTwo的实例,因此您将返回的值视为0,因为这些与{B.InnerOne无关。 1}}或B.InnerTwo

以下B构造函数会将xy分配给B.InnerOneB.InnerTwo的实例,这些实例将返回100。

public B(){
    this.x = new InnerOne();
    this.y = new InnerTwo();
}

如果您希望A以您期望的方式工作,您需要从B构造函数中传递您想要的内部类型,并在{{{{}}中创建它们的实例1}}构造函数,类似于:

A

使用 public B():base(typeof(InnerOne),typeof(InnerTwo)) { ... } 可以在Activator.CreateInstance的构造函数中创建这些类型。

如果你总是希望A以这种方式使用,那么Enigmativity的通用解决方案会更好,或者这种方式允许你为A提供多个构造函数,这样你就可以选择传递不同的类型。 / p>

答案 3 :(得分:1)

你可以这样做,但是你必须改变班级A的定义 - 它会变得非常毛茸茸。

此处A

public abstract class A<I1, I2>
    where I1 : A<I1, I2>.InnerOne, new()
    where I2 : A<I1, I2>.InnerTwo, new()
{
    public InnerOne x;
    public InnerTwo y;
    public A()
    {
        this.x = new I1();
        this.y = new I2();
    }
    public class InnerOne
    {
        public virtual double value()
        {
            return 0;
        }
    }
    public class InnerTwo
    {
        public virtual double value()
        {
            return 0;
        }
    }
}

这里B

public class B: A<B.InnerOne, B.InnerTwo>
{
    public B():base(){ }
    public class InnerOne: A<InnerOne, InnerTwo>.InnerOne
    {
        public override double value()
        {
            return 100;
        }
    }
    public class InnerTwo: A<InnerOne, InnerTwo>.InnerTwo
    {
        public override double value()
        {
            return 100;
        }
    }
}