我正在读一本关于设计模式的书,其中有关于利斯科夫替换原则的这一章,其中说要这样做(以及其他任务)来实现该原则:

子类的方法中的参数类型应该与超类的方法中的参数类型匹配或比超类的方法中的参数类型更抽象.听起来很迷惑吧?让我们举个例子.

假设有一个类有一个应该用来喂cat 的方法:Feed(Cat C).
客户端代码始终将CAT对象传递给此方法.

Feed Good:假设您创建了一个覆盖该方法的子类,以便它可以喂养任何动物(cat 的超类):◦(Animal C).现在,如果您将这个子类的对象而不是超类的对象传递给客户端代码,一切仍然可以正常工作.这种方法可以养活所有的人 动物,所以它仍然可以喂客户经过的任何cat .

◦错误:您创建了另一个子类,并将Feed方法限制为只接受孟加拉cat 科动物(cat 科动物的一个子类):Feed(BengalCat C).如果您将客户端代码与这样的对象链接,而不是与原始类链接,客户端代码会发生什么情况?由于该方法只能喂养特定品种的cat ,因此不会为客户端传递的普通cat 提供服务, destruct 所有相关功能.

在我看来一切都很好,直到我决定try 用C#实现这个例子.
为了更好地理解示例中的"好"部分,我编写了以下代码:

public class Animal { }
public class Cat : Animal { }


public class AnimalFeeder
{
    public virtual void Feed(Cat c)
    {
        Console.WriteLine("Feeding a cat...");
    }
}

public class GenericFeeder : AnimalFeeder
{
    public override void Feed(Animal a) // Compile Error - No suitable method found to override 
    {
        Console.WriteLine("Feeding an animal...");
    }
}

唯一的问题是我得到了上面的错误,
可能我误解了示例,没有编写正确的代码,
如果是,有没有人能帮我以正确的方式更正代码?

提前谢谢您!

推荐答案

假设你所指的书是Alexander Shvets的《Dive Into Design Patterns》,我在网上找到了这本书的可读性副本,在你的摘录之后实际上有以下引述:

在大多数现代编程语言中,尤其是静态类型的编程语言(Java、C#等)中,这些规则都是内置在语言中的.您将无法编译违反这些规则的程序.

我还在by Tamerlan Gudabayev on dev.to号帖子中找到了对这些动物饲养器类的准确描述(这让我对dev.to的版权规则提出了质疑).这里的示例使用的编程语言是PHP,它是动态类型的,因此不会遇到试图用C#实现它时遇到的问题.


因此,不幸的是,LSP的描述不是best.对我来说,这个描述把两件事混为一谈,过于专注于将AnimalFeeder子类化.

相反,LSP侧重于一种简单的 idea ,即您可以将更具体的对象传递到需要基类型的对象中.所以把这个应用到AnimalFeeder的例子中:让我们假设您的Feed方法喂养一只动物,即AnimalFeeder.Feed(Animal).然后,通过LSP,您还可以向该方法传递特定的动物,例如一只cat ,它应该可以很好地工作,因为Cat将是Animal的子类.

当然,对于AnimalFeeder的类型层次 struct 以及是否有子类,这是不特定的.但如果从相反的Angular 看,您也可以在那里应用LSP.让我们假设有一个方法接受AnimalFeeder:

public void Test(AnimalFeeder feeder)
{
    Animal animal = GetAnimalFromSomewhere();
    feeder.Feed(animal);
}

因此,在这里您可以再次应用LSP来查看AnimalFeeder个子类的约束.如果一个AnimalFeeder的子类现在有一个不能处理any个动物的Feed方法,那么这里就违反了LSP.

Csharp相关问答推荐

子组件:如何根据另一个组件的状态启用输入

IComponition.获取IReadOnlyCollection的返回默认属性值

如何在Visual Studio中为C# spread操作符设置格式规则?

当打印一行x个项目时,如何打印最后一行项目?

注册通用工厂的C# Dep注入

. NET 8 HttpClient post参数将其情况更改为camel'

应该使用哪一个?"_counter += 1 OR互锁增量(ref_counter)"""

EF Core. Income和. AsNoTracking正确用法

在发布表单时绑定包含附加(嵌套)列表的对象列表的正确语法是什么

Azure Function应用(. NET 8)不将信息记录到应用洞察

TagHelpers在新区域不起作用

EF核心新验证属性`DeniedValues`和`StringCompison`不起作用

.NET 6:如何防止系统生成的日志(log)?

如何从另一个类的列表中按ID取值

如何在.NET MAUI中最大化GraphicsView的大小?

在C#ASP.NET内核中使用INT AS-1进行控制器场景的单元测试

.NET Google Workspace API获取错误CS0266

如何使用ODP.NET C#设置Oracle会话时间长度限制

Maui:更改代码中的绑定字符串不会更新UI,除非重新生成字符串(MVVM)

反序列化我以前使用System.Text.Json序列化的文件时出现异常