为什么我不能使用基类的对象访问在派生类中声明的变量

时间:2017-07-08 16:58:19

标签: c# inheritance

大家晚上好

我在两个类中创建了两个类ShapeRectangleDraw()方法,Rectangle类是来自Shape的派生类。我在Rectangle中声明了一个名为num的公共变量,并为其初始化了一个值。

在主类中,我以下列方式创建了一个类型为class的对象。

Shape s = new Rectangle();

现在,当我尝试访问矩形类的num变量时,它会出错

  

“/ Users/apple/Projects/Practice/Practice/Program.cs(33,33):错误   CS1061:'Shape'不包含'num'和no的定义   扩展方法'num'接受'Shape'类型的第一个参数   可以找到(你错过了使用指令或程序集   参考?)(CS1061)(实践)“

我的理解:语句new Rectangle();在内存中创建类型为Rectangle的对象,其引用存储在Shape类型的对象中。因此,对象应该可以访问矩形类中定义的变量num。请让我理解这个概念为什么我们无法从num类型的对象访问Shape变量。

请找到附带的截图。

Screenshot of code with error

3 个答案:

答案 0 :(得分:0)

尝试更改

Shape s - new Rectangle();

Rectangle s = new Rectangle();

Shape s没有num,因为Shape不是Rectangle

答案 1 :(得分:0)

您可以使用动态语言访问s.num。在动态语言中,成员可用性的类型测试和测试在运行时执行。 s的运行时类型为Rectangle,即s引用类型为Rectangle的对象。但是,C#是一种静态和强类型的语言。即这些测试在编译时执行。在编译时,只有通过静态类型s可用的成员才可见。 num不是静态类型Shape的成员,因此不可见。

Shape对象(实际上是任何类)看到自己的成员及其祖先的成员,即继承成员,如果它们是公共的或受保护的。它无法查看派生类的成员(此处为Rectangle),因为它们未在Shape中声明,如果在2个不同的程序集中声明了2个类,则它们在编译时也不可知。

基类必须包含自身及其后代共有的所有内容。 如果您仍希望从Rectangle变量访问Shape内容,则可以投射(假设VS 2017):

if (shape is Rectangle rect) {
    var x = rect.num;
}

但是,这通常是OO设计糟糕的表现。在这种情况下,您可以简单地覆盖ToString

public class Rectangle : Shape
{
    private int num = 10;

    ...

    public override string ToString()
    {
        return $"Rectangle num = {num}";
    }
}

...

Shape shape = new Rectangle();
Console.WriteLine(shape); // Uses ToString() of rectangle.

答案 2 :(得分:0)

Shape类型的对象对象只能访问Shape类中定义的成员。您有两种选择:

  1. num班级中定义ShapeRectangle班级可以使用s

  2. 将对象Rectangle投射到css naming convention类型以便能够使用它。

  3. 原则上,我更喜欢选项#1。应该定义基类中的基类和子类使用的属性和方法。

相关问题