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.英语是我的第二语言,所以我对错误感到抱歉。

C# 如何从基类转到派生类而不违反封装

你实际上没有。考虑你有方法.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 方法将使用值填充可视控件,具体取决于它接收的字符串参数。

这就是你想要的吗?

每次类之间有一个共同的行为时,都应该将其表示为基类中的一个方法。

每当派生类或类子集需要更改基类的行为时,都应重写该方法。这个概念被称为多态性。

我会避免使用佩德罗建议的"新"关键字,但这只是我的意见。