C# 如何从基类转到派生类而不违反封装
本文关键字:封装 派生 基类 | 更新日期: 2023-09-27 18:37:07
之前在SO上已经提出了向下铸造的问题,但我找不到任何关于如何正确避免它的解释。
例如,请考虑此层次结构。
abstract class NetworkDevice
{
//some common fields & properties
}
class Router : NetworkDevice
{
//some router-specific fields & properties & methods
}
class Switch : NetworkDevice
{
//some switch-specific fields & properties & methods
}
在某些时候,我想根据路由器和交换机的共同属性(因此是基类)来类似地对待路由器和交换机以及其他网络设备,但在某些时候 - 考虑到它们的独特品质,情况有所不同。
问题是 - 如何正确从一种情况切换到另一种情况?
比如说,有List<NetworkDevice>
,从某个来源收到。现在,当用户从列表中选择一个NetworkDevice
时,我需要显示所有特定信息(特定于交换机/路由器/等),并使用值填充可视控件。
我的理解是,有人必须将NetworkDevice向下投射到派生类才能做到这一点,但是有人会怎么做才能保留封装呢?
我目前可以看到的唯一方法是像这样修改NetworkDevice
:
abstract class NetworkDevice
{
Type type {get; set;}
//etc...
}
或出于相同目的定义Enum NetworkDeviceType { Router, Switch, ...}
。
无论哪种方式,我们最终都会得到这种代码:
void DifferenciateNetworkDevice (NetworkDevice device)
{
...
switch (device.type)
{
case Switch: //or NetworkDeviceType.Switch
ShowSwitchProperties(device as Switch);
break;
case Router: //or NetworkDeviceType.Router
ShowRouterProperties(device as Router);
break;
...
}
}
这会导致冗长的switch
语句,并且似乎不是很概括。那么,我错过了什么?正确的方法是什么?
附言:我希望在这种情况下,反思不是一种常见的方法,可以避免。P.P.S.英语是我的第二语言,所以我对错误感到抱歉。
你实际上没有。考虑你有方法.Flush() 在所有 3 层抽象中,您可以使用关键字 "new" "覆盖"非虚拟方法,如下所示:
abstract class NetworkDevice
{
public void Flush() {
// Logic
}
public void PowerDown() {
// Logic
}
}
public class Router : NetworkDevice
{
// New stuff, ignoring the one below
public new void Flush() {
// new magic
}
public void Routaree() {
// router specific magic
}
}
public class Switch : NetworkDevice
{
public void Switcharoo() {
// Switch centric stuff
}
}
在上面的例子中,路由器和交换机都将使用"Flush()"的新实现,不同于抽象类实现。
您也可以将"虚拟"放在需要重新实现的方法前面,并使用"覆盖"而不是"新"来实现几乎相同的目标。
我只会使用 显示属性(设备。GetType()。ToString());
此 ShowProperties 方法将使用值填充可视控件,具体取决于它接收的字符串参数。
这就是你想要的吗?
每次类之间有一个共同的行为时,都应该将其表示为基类中的一个方法。
每当派生类或类子集需要更改基类的行为时,都应重写该方法。这个概念被称为多态性。
我会避免使用佩德罗建议的"新"关键字,但这只是我的意见。