如何访问列表中的子类方法?

时间:2016-03-27 21:53:10

标签: c# .net list

我有一个父类" bankAccount"有两个子类,然后这些子类派生到其他子类。我想创建一个孙子对象并将其保存在List中,然后能够与孙子孙女的方法进行交互。但是,我似乎无法访问这些类的方法。我所能做的只是与祖父母班级的方法互动。

这就是我在List中添加子类的方法。

List<bankAccount> accounts = new List<bankAccount>();
accounts.Add(new VistaAccount(nAccount,pass,nameClient,balance,interest));

4 个答案:

答案 0 :(得分:2)

首先,了解为什么C#不允许您在银行帐户列表中执行此操作。

如果您有各种银行帐户的列表,那么无论您对其中任何做什么,都需要适用于每个。您不能在对象上调用方法,除非该对象保证具有该方法。静态类型系统可以尽早向您发出警告。

话虽如此,如果你真的知道你只有少数几种银行账户,你可以单独列举它们:

foreach(var account in accounts.OfType<VistaAccount>())
{
    // call methods specific to "Vista" accounts
}

foreach(var account in accounts.OfType<OtherAccount>())
{
    // call methods specific to "Other" accounts
}

现在请记住,从长远来看,这种方法不能很好地扩展。如果将来引入更多的子类型,您可能需要回到那个位置并添加更多特殊情况。

如果您希望在每个帐户上执行特定操作,并且该操作的详细信息对于每种类型的帐户都会有所不同,那么就有更好的方法。只需在您的基本银行帐户类型上声明一个抽象方法:

public abstract void Operation();

然后在每种帐户中实施(override)该方法,并附上特定于此类的说明。

  • 从长远来看,这可以很好地扩展,因为无论何时引入更多帐户类型,您都不必记得引入特殊情况。为您未来的自我或未来的代码维护者记录一件事。
  • 它更方便,因为如果您忘记为子类型指定操作,您将在编译时获得一条好消息。所以有一个很好的安全网,以防你忘记这样做。
  • 因为现在各种银行账户都可以保证支持该操作,编译器很乐意让您甚至可以在银行账户列表上拨打电话。您不需要我最初提议的手动类型检查。

答案 1 :(得分:2)

简单地说:你想做什么是不可能的,实际上是错误的。

高级:您可以使用反射或在投射后完成所需但仍然非常错误。

您只能在BankAccount内的项目上使用基类(list<BankAccount>)中声明的方法。如果您需要孙子对象的行为不同,您应该覆盖孙子类中的方法(在BankAccount类中必须是虚拟的)。

答案 2 :(得分:1)

您无法通过父级的api访问孩子的成员。你需要引用一个暴露成员的类型的引用,或者通过强制转换(这通常是坏/丑)或者通过定义对于要开始的子类型的引用。

如果您确实需要子对象列表,为什么要使用父母列表?如果不是更多,你需要重新考虑当前方法的设计。

答案 3 :(得分:1)

这与Liskov Substitution Principle有关。你有一堆对象 - 有些可能属于VistaAccount类型,有些属于不同类型,但它们都继承自bankAccount。通过将它们放在List<bankAccount>中,您将它们全部作为基类bankAccount投射。

在这种情况下,关键在于您将所有这些视为bankAccount,并且根本不应该是VistaAccount或其他类型。唯一重要的类型是bankAccount,子类无关紧要。

如果您正在检查这些个体实例,看看它们究竟是什么类型,那么可能会出现问题。如果你必须检查每个对象以查看它的类型,那么目的就会失败。根据其逻辑结论,它可能只是List<object>

您想要的(如果可能)是一种设计,您在每个类上调用的方法是相同的,并且只有这些方法的行为不同。例如,CircleSquareTriangle都可以从Shape继承,每个都会覆盖Draw()方法。每个班级的方法都不同。但是如果你将它们全部放在List<Shape>中,那么你可以在每个方法上调用Draw()方法而不知道每个方法的子类。