具有一个包含派生类型的对象的列表,然后在需要调用特定于一种类型的方法时通过类型检查对其进行过滤是一种很好的做法吗?从我读到的内容中,类型检查是某种代码味道,它表明OOP没有得到充分利用。
我对所有子类型的对象使用通用列表,因为我想在所有对象上调用一些通用方法。但是某些方法特定于某些子类型,如果要调用该方法,则需要按类型过滤对象。
public abstract class ParentType
{
public abstract void CommonMethod();
}
public class DerivedTypeA : ParentType
{
public override void CommonMethod()
{
//do something
}
public void TypeASpecificMethod()
{
//do something
}
}
public class DerivedTypeB : ParentType
{
public override void CommonMethod()
{
//do something
}
public void TypeBSpecificMethod()
{
//do something
}
}
static void Main()
{
List<ParentType> objects = new List<ParentType>()
{
new DerivedTypeA(),
new DerivedTypeA(),
new DerivedTypeB(),
new DerivedTypeB()
}
//Call common method on all objects in a list
foreach(var obj in objects)
{
obj.CommonMethod();
}
//Call only specific method for DerivedTypeA objects
foreach(var obj in objects)
{
if(obj is DerivedTypeA derivedAObj) //type checking needed
{
derivedAObj.TypeASpecificMethod();
}
}
}
您是正确的,这不是OOP。 OOP解决方案将是使每种类型的CommonMethod
的实现调用适合于该类型的其他特定方法。
是的,您提供的代码违反了SOLID原则,因此应避免使用if语句检查类型是否正确。您可以使用策略模式和工厂在运行时创建不同的策略。
让我们考虑以下代码:
foreach (var obj in objects)
{
if (obj is DerivedTypeA)
{
obj.TypeASpecificMethod();
}
}
随着您的逻辑发展,您可能最终会遇到这样的事情:
foreach (var obj in objects)
{
if (obj is DerivedTypeA)
{
obj.TypeASpecificMethod();
}
else if (obj is DerivedTypeB)
{
obj.TypeBSpecificMethod();
}
else if (obj is DerivedTypeC)
{
obj.TypeCSpecificMethod();
}
}
上面的代码违反了Open-closed原则:
应该为扩展打开代码,但是为修改而关闭
由于这是一个假设的问题,很难为您提供解决方案...
在现实世界中,您可以查看控制反转。依赖注入和工厂模式是IoC的流行形式。
绝对没问题,相反,您可以使用OOP正确地执行操作。
首先,使用多态性的主要目的是解析具有相同基本类型的不同类型的对象的列表,然后调用相同的方法。
然后您使用类型匹配将特殊情况应用于具有相同基本类型的不同类型对象的非特定对象列表,以仅对特定子类型的对象起作用。
这是两个基本的案例研究。
您什么都没犯。
例如,在现实世界中,洗车机:
将以相同的方式清洗不同类型汽车的外部:它将一次又一次地通过汽车,并在每个汽车上应用相同的方法,这是您的第一个循环-他与汽车类型无关因为它们是汽车。