【问题标题】:Is it ok to override a virtual method but provide no implementation?是否可以覆盖虚拟方法但不提供实现?
【发布时间】:2020-11-29 09:56:29
【问题描述】:

我正在尝试为游戏创建一个类 heirachy,其中有一个 Item 类,它是游戏中所有项目的基类。问题是某些派生物品(如药水)可能无法实现该物品定义的某些抽象方法。

派生类可以实现“什么都不做”的抽象方法吗?

示例:https://dotnetfiddle.net/jJABN1

using System;
using System.Collections.Generic;

public abstract class Item
{
    public abstract void Use(); 
}

public class Potion : Item
{
    public override void Use()
    {
        // do nothing
        return;
    }
}

public class Sword : Item
{
    public override void Use()
    {
        Console.WriteLine("Sword used!");
        return;
    }
}
    
                    
public class Program
{
    public static void Main()
    {
        List<Item> items = new List<Item>();
        
        Item potion = new Potion();
        Item sword = new Sword();
        
        items.Add(potion);
        items.Add(sword);
        
        for (int i = 0; i < items.Count; i++)
        {
            Item item = items[i];
            item.Use();
        }
    }
}

【问题讨论】:

标签: oop overriding abstract


【解决方案1】:

Robert Martin 的 SOLID 原则之一 - Interface Segregation Principle 解决了这种情况。它基本上是说客户端不应该暴露于它不需要的方法。

一个违反接口隔离原则的例子

// Abstraction

public abstract class Printer
{
    public abstract void Print();
    public abstract void Scan();
}


// Implementations

public class SomeAllInOnePrinter : Printer
{
    public override void Print()
    {
        Console.WriteLine("Printing...");
    }

    public override void Scan()
    {
        Console.WriteLine("Scanning...");
    }
}

public class SomeBasicPrinter : Printer
{
    public override void Print()
    {
        Console.WriteLine("Printing...");
    }

    public override void Scan()
    {
        // Basic printers can't scan
    }
}

这通常通过将一个抽象类分离为多个较小的抽象类来解决,这些抽象类可以选择性地相互继承:

// Abstractions

public abstract class Printer
{
    public abstract void Print();
}

public abstract class AllInOnePrinter : Printer
{
    public abstract void Scan();
}


// Implementations

public class SomeAllInOnePrinter : AllInOnePrinter
{
    public override void Print()
    {
        Console.WriteLine("Printing...");
    }

    public override void Scan()
    {
        Console.WriteLine("Scanning...");
    }
}

public class SomeBasicPrinter : Printer
{
    public override void Print()
    {
        Console.WriteLine("Printing...");
    }
}

【讨论】:

  • 啊哈!我现在明白了,这非常有用,谢谢!
【解决方案2】:

从技术上讲,可能存在一种极端情况(应该不常见!),其中派生类不需要实现所有方法,在这种情况下,我宁愿它重写并抛出错误以发出信号用户认为不应使用此方法。

也就是说,在提供的示例中只有一个方法,所以问题是:如果派生类不需要此方法 - 为什么需要继承抽象类?如果只是为了提供一个可以理解的示例 - 但更好地改进示例以包含 在派生类中使用的其他方法。

【讨论】:

  • 感谢您的回复,我想我需要从 Item 基类派生,以便我可以将两个项目存储在同一个列表中?我已更新示例以将列表包含在主函数中
  • @RichardBamford 您没有将此问题标记为特定于 c++ 的问题,因此我假设这是一个一般性的 OOP 问题。因此,许多面向对象语言允许使用interface,这与抽象类的不同之处在于一个类可以实现多个接口(而大多数语言由于diamond-problem而将继承限制为仅一个类) .在这个特定的上下文中,听起来接口比抽象类更合适。
猜你喜欢
  • 2012-10-26
  • 1970-01-01
  • 2021-11-02
  • 2021-05-24
  • 1970-01-01
  • 2014-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多