Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oop 如何使用OO和SOLID原则更好地设计它?_Oop_Solid Principles - Fatal编程技术网

Oop 如何使用OO和SOLID原则更好地设计它?

Oop 如何使用OO和SOLID原则更好地设计它?,oop,solid-principles,Oop,Solid Principles,我发现了很多关于相关问题的类似帖子,这个回复很接近,但并没有完全回答我的问题 假设我有一个接口: public interface IShape { decimal GetArea(); } 然后我使用这个接口创建了3个类 public class Rectangle : IShape { public decimal GetArea() { ... } } public class Triangle : IShape { public

我发现了很多关于相关问题的类似帖子,这个回复很接近,但并没有完全回答我的问题

假设我有一个接口:

public interface IShape
{
    decimal GetArea();
}
然后我使用这个接口创建了3个类

public class Rectangle : IShape
{
    public decimal GetArea()
    {
        ...
    }
}

public class Triangle : IShape
{
    public decimal GetArea()
    {
        ...
    }
}

public class Circle : IShape
{
    public decimal GetArea()
    {
        ...
    }
}
现在我想添加一个
int GetNumberOfSides()
函数(或者只与我的一些IShape相关的其他函数)。显然,这与Circle类无关。如果我有一个
列表
对象,并且想要在相关iShape上迭代调用这个函数,那么您将如何使用面向对象的设计原则来解决这个问题

我可以向我的IShape接口
boolHassides{get;set;}
添加一个布尔值,并运行任何逻辑,但是我需要强制转换到特定的类才能访问
GetNumberOfSides()
函数。我知道这是不对的,因为感觉不对,但我不知道该怎么做

我曾经考虑过使用另一个接口
ISidedShape
,它继承自
IShape
,但是回到我的列表的迭代,我怎么知道哪些形状有这个特定的方法呢

任何帮助都将不胜感激


谢谢

如果您想采用面向对象的方式,您可以添加一个接口,因为您可以在大多数语言中实现任意数量的接口:

public interface IPolygon
{
    int GetNumberOfSides();
}

public class Rectangle : IShape, IPolygon
{
    public decimal GetArea() { return 0; }
    public int GetNumberOfSides() { return 4; }
}
的确,所有多边形都是形状;然而,在过去的几年中,许多OOPER认识到继承既有强大的功能,也有难以置信的危险,而且一般来说,如果有必要的话,复合关系比层次关系更受欢迎


我不得不说,虽然这是一个很好的学术练习,但典型的“形状”OOP示例通常不能很好地转化为“真实世界”,因此,许多程序员发现自己过于复杂化了原本可能是简单的方法。由于一切都必须是对象,我们被迫将数据映射到对象模型上,这通常意味着我们强制将数据与范式相适应,或开发结构使其工作,而不是简单地使用数据。“简单”是王者,复杂性是敌人。

如果您的代码中的某些地方已经有了
列表
(因此您依赖于
IShape
多态性),我认为最好的解决方案是将
GetNumberOfSides()
添加到
IShape
中,并按如下方式实现它

public class Circle : IShape
{
    public decimal GetNumberOfSides()
    {
        return 0;
    }
}
如果您仍处于“设计”阶段,并且实际上没有使用
List
的代码,则可以实现第二个接口
IPolygon
(与@Josh answer完全相同)

这两种解决方案中的任何一种都适合(取决于当前如何使用
IShape
)和“OOP方法”。我不能说哪一个更好,因为您没有向我们展示您的真实代码(并且基于形状示例做出这样的决定是不相关的)


但是,我不鼓励的唯一方法是在
IShape
中添加
hasSides
方法,因为每次迭代
列表时,代码都会被大量
if
弄得乱七八糟,因此测试和维护都是一场噩梦。因此,请让多态性处理分支,而不是使用
上的
if
进行手动分支 如果将方法getSides()添加到IShape接口,当该接口由Circle实现时,它将违反LSP,因为它没有边。
因此,您希望创建一个新的IPolygon界面,如其中一篇文章中所述,这样它将同时遵循Is和LSP

不能
循环
简单地
返回0用于边数?其他奇怪的形状呢,比如半圆?这将合法地有1个“边”,以及1个“边以外的东西,取决于你如何定义边”。也许“边”不是你要找的词?用一个更贴切的名称来命名这个术语,建模可能更有意义。我的例子可能不是最好的。我正在努力寻找一个例子,但没有使用我的实际场景,这需要其他知识。我理解你关于返回0的观点,但这也不正确。为什么感觉不正确?这是完全合乎逻辑的。
IShape
是一种分散注意力的东西。就这个问题而言,我建议
IShape
Object
没有区别。问问你自己,如果我有一个
列表
,并且想要迭代并调用相关对象上的函数,我将如何使用面向对象的设计原则来解决这个问题?@jrahhali,我同意在这个例子中它是非常有意义的。我给出的例子与我的现实生活情景并不直接相符。在我的场景中,我有两种类型,一种是从另一种继承而来的,并提供了附加的函数,这些函数只有在第二种上才有意义。所以在一个接口中实现它们是没有意义的。谢谢Josh。当在
列表上循环时,您会使用
is IPolygon
来确定是否将其转换为
IPolygon
吗?如果在
列表上循环时,您不会只是将
if hasSides
替换为
if xxx is IPolygon
?@user1244893如果您提前使用
IPolygon
,一个可接受的选项(可能)是也有一个
列表
。但是,您现在需要维护两个列表,而不是一个。因此,第一种方法(将
GetNumberOfSides
添加到
IShape
)对我来说似乎是最容易维护的方法。