大家晚上好
我在两个类中创建了两个类Shape
,Rectangle
和Draw()
方法,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
变量。
请找到附带的截图。
答案 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类中定义的成员。您有两种选择:
在num
班级中定义Shape
,Rectangle
班级可以使用s
。
将对象Rectangle
投射到css naming convention
类型以便能够使用它。
原则上,我更喜欢选项#1。应该定义基类中的基类和子类使用的属性和方法。