请解释 Shape r = new Square() 的结果以及为啥 Square 的方法不可用

Posted

技术标签:

【中文标题】请解释 Shape r = new Square() 的结果以及为啥 Square 的方法不可用【英文标题】:Please explain the outcome of Shape r = new Square() and why Square's methods aren't available请解释 Shape r = new Square() 的结果以及为什么 Square 的方法不可用 【发布时间】:2021-10-20 09:42:29 【问题描述】:

我正在研究 Jeff Fritz 的 c# tutorial videos,并且有一些类似这样的代码使用抽象类:

public abstract class Shape 
public class Rectangle : Shape 
public class Square : Rectangle 
    public string SquareOnlyMethod()  return "I am a square"; 



public static void Main()

    Square s = new Square(); 
    
    Console.WriteLine(s.GetType());            // Square
    Console.WriteLine(s is Shape);             // True
    Console.WriteLine(s is Rectangle);         // True
    Console.WriteLine(s is Square);            // True
    Console.WriteLine(s.SquareOnlyMethod());   // I am a square
    
    Shape r = new Square();
    
    Console.WriteLine(r.GetType());            // Square
    Console.WriteLine(r is Shape);             // True
    Console.WriteLine(r is Rectangle);         // True
    Console.WriteLine(r is Square);            // True
    Console.WriteLine(r.SquareOnlyMethod());   // 'Shape' does not contain a definition for 'SquareOnlyMethod' and no extension method 'SquareOnlyMethod' accepting a first argument of type 'Shape' could be found

有人可以解释一下吗?

    当我们执行Shape r = new Square(); 时实际创建了什么?是Shape 还是Square? 为什么GetType返回Square却找不到Square类中的方法?

Jeff 说(如果我理解正确的话)“‘Shape` 是用 Square 的足迹创建的”,然后继续前进。

Fiddle

【问题讨论】:

"它是形状还是正方形?"两者都是,因为所有 Square 对象也是 Shape 对象。 您创建使用 new 关键字初始化的内容,在本例中为 Square 实例。但是您将它分配给它的基本类型Shape 的变量。通过这种方式,您隐藏了它是Square 的事实。你总是可以将它转换回Square,然后你也可以使用SquareOnlyMethod。因此,即使它仍然是 Square,编译器也不允许使用在 Square 中定义的方法,如果它被声明为 Shape,因为不是每个 Shape 都有这个方法。 【参考方案1】:

您看到的问题始于以下行 Shape r = new Square();,因为即使您正在创建 Square 但使用基本类型。我假设 Jeff 试图向您展示的概念是 多态性,可以在此处查看形状问题的更好示例https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/object-oriented/polymorphism。

在 Microsoft 示例中,您可以看到基类为任何派生类(形状)提供了通用功能,以利用、扩展或覆盖。因此,您可以潜在地将不同 Shape 子代的单个数组视为 Shapes,并跨任何子 shape(因此有多种形式)访问或调用方法(虚拟覆盖)。

var shapes = new List<Shape>

    new Rectangle(),
    new Triangle(),
    new Circle()
;

// Polymorphism at work #2: the virtual method Draw is
// invoked on each of the derived classes, not the base class.
foreach (var shape in shapes)

    shape.Draw();

【讨论】:

谢谢。这是实例化期间“装箱”的一个例子吗?创建了一个 Square 但只展示基类 Shape 的方法?让我困惑的是 GetType 位。 不,当您需要使用值类型代替引用类型时会发生装箱,例如object integer = 1。在这里,所有类型都是引用类型,因此不会发生装箱。 @EvilDr GetType 返回运行时类型,因为运行时的实例类型是 Square - 这就是您将看到的。查看 docs.microsoft.com/en-us/dotnet/api/… 和 docs.microsoft.com/en-us/dotnet/api/… 这些是了解差异的好参考。

以上是关于请解释 Shape r = new Square() 的结果以及为啥 Square 的方法不可用的主要内容,如果未能解决你的问题,请参考以下文章

请高手指点:回归分析中的“multiple r ”“R Square ”“Adjusted R Square”“标准误差 ”是啥意思?

计算形状Shape(圆Circle,矩形Square ,正方形Rectangle)的面积周长

多态

ssemsermse r-square

[Design Pattern] Factory Pattern 简单案例

每日打卡-14