我在将继承的类型转换为基类时遇到一个基本问题。我知道这通常是不可能的,即您可以将派生类强制转换为其基类,但事实并非如此。这是我正在努力的示例片段:
假设我已经定义了一个抽象类来表示计算机PCI卡:
public abstract class PciDevice
{
public abstract int GetDeviceId();
public abstract String GetVendorName();
}
现在,我创建了3种类型的继承类(设备):
public class GraphicsCard : PciDevice
{
public override int GetDeviceId() { return 1666; }
public override String GetVendorName() { return "CoolCorp"; }
int trianglesPerSecond;
ChipsetTypeEnum chipsetType;
}
public class AudioCard : PciDevice
{
public override int GetDeviceId() { return 1999; }
public override String GetVendorName() { return "ShinyCorp"; }
int numChannels;
int samplingRate;
}
public class Modem : PciDevice
{
public override int GetDeviceId() { return 1234; }
public override String GetVendorName() { return "BoringCorp"; }
public int baudRate;
bool faxEnabled;
}
现在,我在计算机内部定义了一个“插槽”:
public class PciCardSlot
{
private int slotId;
private int clockFreq;
private PciDevice cardInSlot;
public PciDevice getCard() { return cardInSlot; }
public void setCard(PciDevice card) { cardInSlot = card; }
}
我有一个插槽数组来代表计算机中的所有插槽:
PciCardSlot [] pciSlotsInComputer = new PciCardSlot[6];
然后,给定插槽ID,我定义一个函数来检索PciDevice对象:
public PciDevice getInsertedCard(int slotId)
{
return pciSlotsInComputer[slotId].getCard();
}
到目前为止,一切都很好。现在,在代码中的某个地方,我实例化了AudioCard,GraphicsCard和Modem对象,并将它们分配给插槽。
AudioCard a = new AudioCard();
Modem b = new Modem();
GraphicsCard c = new GraphicsCard();
PciCardSlot s0 = new PciCardSlot(); s0.setCard(a);
PciCardSlot s1 = new PciCardSlot(); s1.setCard(b);
PciCardSlot s2 = new PciCardSlot(); s2.setCard(c);
pciSlotsInComputer[0] = s0; pciSlotsInComputer[1] = s1; pciSlotsInComputer[2] = s2;
然后,我有一个如下所示的函数,旨在对Modem对象进行操作:
public setBaudRateForModem(int slotId, int rate)
{
((Modem)getInsertedCard(slotId)).baudRate = rate; // Can not cast!!!
}
...
// I know that slot 1 contains a modem, so I do:
setBaudRateForModem(1, 9600);
由于我正尝试从PciDevice对象投射到从PciDevice派生的Modem对象,因此上面的转换不起作用。
我一直在阅读有关此内容的文章,几乎在我所看到的所有地方,人们似乎都认为,如果您需要将基类转换为成员类,那么您的设计就会很糟糕。我的班级层次结构设计不好吗?有什么建议么?谢谢阅读。
最佳答案
好吧,我认为对PciDevices进行多态处理没有内在的问题。框架中内置了许多实例,在这些实例中,有必要将对象转换回“上下文已知”类型。
但是,BaudRate是仅调制解调器属性,因此其定义和逻辑应位于该类中。具有该特定用途的功能不应更高级别。
通常,您的get函数应该是拥有对象上属性的get定义。
本质上,您在尝试访问BaudRate之前需要了解调制解调器的位置。
例如,如果您想更新所有Modem的BaudRates并且Modem类被很好地封装,则您应该能够执行以下操作
void UpdateModemBaudRates(int baudRate)
{
foreach(PciCardSlot slot in pciSlotsInComputer)
{
Modem modem = slot.CardInSlot as Modem;
if(modem != null)
{
modem.BaudRate = baudRate
}
}
}
如果很难做到这一点,请查找
as
和is
关键字。当然,Linq拥有更现代的方式来执行此操作,这是克里斯的评论启发的一种方式。
void UpdateModemBaudRates(int baudRate)
{
pciSlotsInComputer.Select(s => s.CardInSlot).OfType<Modem>().AsParallel().ForAll<Modem>(modem => modem.BaudRate=baudRate);
}
关于c# - 继承与转型,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5595699/