可以覆盖虚拟方法但不提供实现吗?

Is it ok to override a virtual method but provide no implementation?

我正在尝试为游戏创建 class 继承权,有一个物品 class 是游戏中所有物品的基础 class。问题是一些派生物品(如药水)可能不会实现物品定义的一些抽象方法。

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

示例: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();
        }
    }
}

从技术上讲,可能存在一种边缘情况(应该不常见!),其中派生 class 不需要实现所有方法,在这种情况下我宁愿它覆盖和抛出一个错误来通知用户不应使用此方法。

也就是说,在提供的示例中只有一种方法,所以问题是:如果派生 class 不需要此方法 - 为什么需要继承抽象 class 开头?如果它只是为了提供一个可以理解的示例 - 但更好地改进示例以包括 are 在派生的 class.

中使用的其他方法

Robert Martin's SOLID Principles - 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
    }
}

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

// 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...");
    }
}