【问题标题】:Method overriding and Method overloading from abstract class抽象类的方法覆盖和方法重载
【发布时间】:2014-02-06 12:17:57
【问题描述】:

我必须创建一个名为 Shape 的抽象类。

这个抽象类包含一个抽象方法GetArea(double height, double width);

然后我将继承如下。

Rectangle : Shape

Oval : Shape

所以在这种情况下,我可以用方法中必需的 2 个参数覆盖 GetArea()

现在我必须制作Circle : Oval inheritance

所以再次计算面积我必须覆盖GetArea 方法。

但在这种情况下,从逻辑上讲,半径只需要一个参数。

在这种情况下我该怎么办?

如果我在 shape 类中使用一个参数 GetArea(double height) 重载另一种方法,那么在这种情况下,我必须在 RectangleOval 类中覆盖它,这不是必需的吗?

什么是可能的解决方案?

Shape 类中的方法必须是抽象的,子类中的方法必须是参数化的。

【问题讨论】:

  • 你可以重复使用相同的方法,宽度和高度应该相同,所以r = w/2r = h/2。虽然它并不能真正回答您的 OO 问题!

标签: c# inheritance polymorphism overloading overriding


【解决方案1】:

您可以将形状的参数作为构造函数的一部分,或者为它们创建属性。

public class Rectangle : Shape
{
    public double Width{ get; set;}

    public double Height{ get; set;}   

    public double GetArea() {return Width * Height;}

}

【讨论】:

  • @AlexD 那是override :)
  • 子类中的方法必须参数化。
【解决方案2】:

方法参数是方法定义的一部分,因此在覆盖它们时无法更改。

我个人会添加一个无参数的方法来计算面积,并在派生类中添加特定于类的属性。

public abstract class Shape {
    public abstract double GetArea();
}

public class Rectangle : Shape {
    public double Height { get; set; }
    public double Width { get; set; }
    public override double GetArea() {
        return Height * Width;
    }
}

public class Oval : Shape {
    public double Radius { get; set; }
    public override double GetArea() {
        return ...;
    }    
}

【讨论】:

  • 子类中的方法必须参数化。
  • 请根据您的完整要求更新问题,现在原因尚不清楚。 事实,当您在派生类中重写方法定义时,您无法将参数添加到方法定义中。
【解决方案3】:

如果方法绝对必须有参数(这有点违背了在这里使用 OOP 的目的,因为形状的尺寸应该在对象中定义而不是作为参数传入),那么你必须采取一些措施,我猜宽度和高度和任何东西一样好(尽管这不包括让设计工作具有各种形状)。

这是您可以采取的一种方法:

public abstract class Shape
{
    public abstract double GetArea(double width, double height);
}

public class Oval : Shape
{
    public override double GetArea(double width, double height)
    {
        return Math.PI * width * height / 4;
    }
}

public class Circle : Oval
{
    public override double GetArea(double width, double height)
    {
        if (width != height)
        {
            throw new ArgumentException("width and height of a circle must be equal");
        }
        return base.GetArea(width, height);
    }

    // Class-specific convenence method. 
    // Completely separate from two-parameter version of GetArea
    public double GetArea(double diameter)
    {
        return GetArea(diameter, diameter);
    }
}

如 cmets 中所述,此处GetArea 的单参数版本与inherited 双参数版本完全脱节,但这确实演示了继承链的使用并避免了重复代码。

【讨论】:

    【解决方案4】:

    在您的情况下,您正在处理类实例,因此每个 GetArea 方法不应接收参数。相反,它们应该是相应类的属性:

    abstract class Shape
    {
        abstract int GetArea();
    }
    
    class Circle : Shape
    {
        public double Radius {get; set;}
        public override int GetArea(){ return Math.PI * Radius * Radius;}
    }
    
    class Rectangle : Shape
    {
        public double Width{ get; set;}    
        public double Height{ get; set;}   
        public double GetArea() {return Width * Height;}
    }
    

    【讨论】:

    • 子类中的方法必须参数化。
    • 为什么需要参数化?那没有意义。矩形有一定的面积​​。如果您要测量现有矩形的大小,则没有变量。矩形有一个区域,就是这样。
    • 抱歉,这是任务,所以我们必须在方法中添加参数。
    • 好吧,那么它没有意义......对于一个圆圈,参数是不同的,所以你的 GetArea 不再是多态的。在这种情况下,您不应该使 GetArea 抽象。要么你误解了任务,要么任务错了。
    【解决方案5】:

    我宁愿实现一个接口而不是抽象类,并在方便的地方使用显式接口实现

    public interface IShape {
      ... 
      Double GetArea(Double width, Double height);
    }
    
    // Abstract class
    // It's redundant and here is because it required by the task
    public abstract class Shape: IShape {
    }
    
    public class Oval: Shape {
      ...
      public Double GetArea(Double width, Double height) {
        return Math.PI * width * height / 4; 
      }
    }
    
    public class Circle: Shape {
      ...
      // This method's more convenient
      public Double GetArea(Double diameter) {
        return Math.PI * diameter * diameter * 4;
      }
    
      // Explicit interface implementation: 
      // We have to implement two arguments method
      // however, it's combersome that's why we hide it under
      // explicit interface implementation
      Double IShape.GetArea(Double width, Double height) {
        return this.GetArea(width / 2);
      }
    }
    

    【讨论】:

    • 我必须使抽象类成为必要,因为它是在任务中指定的。
    • @Nirav Kamani:好吧,如果需要抽象类,你可以放它(见编辑),但在这个任务中没有太多意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-02
    • 2013-09-12
    • 1970-01-01
    • 2015-08-20
    • 1970-01-01
    • 2012-07-11
    相关资源
    最近更新 更多