了解继承问题

时间:2009-03-26 04:49:06

标签: c# inheritance

我希望在C#中扩展一个具有一些附加功能的基类。我有现有的代码,它返回我需要转换为扩展版本的基类对象(Account)的数组。

所以我有扩展版本:

class AccountXtra : Account
{
    public int Period { get; set; }
    public int Visitors { get; set; }
    public string ContactName { get; set; }
}

一切都很好。

但是当我有一个Account实例时,如何创建一个新的AccountXtra实例?

我试过了:

//This doesn't work
AccountXtra newInstance = (AccountXtra)accountInstance;
//This also doesn't work
AccountXtra newInstance = new AccountXtra();
newInstance = accountInstance;

5 个答案:

答案 0 :(得分:1)

  

但是当我有一个Account实例时,如何创建一个新的AccountXtra实例?

这是错误的方式 - 您需要创建AccountXtra对象,然后可以将其作为Account对象处理。

顺便说一下,如果您不确定要在列表创建代码中创建哪种类型的对象,则可能需要阅读factory patterns

您可以根据自己遇到的具体问题随意更新问题。

答案 1 :(得分:1)

您无法将基类转换为子类。换句话说,如果对象的类型为“Account”,则无法将其强制转换为“AccountXtra”。但是,如果您有“AccountXtra”类,因为它继承自“帐户”,您可以将其强制转换为帐户。

如果您拥有现有代码的源代码,则需要更改它所谓的“新Account()”构造函数的位置,并将其更改为“new AccountXtra()”。您还应该将“Account”类的实例替换为“AccountXtra”

您可以尝试的另一个想法是在AccountXtra()中创建一个构造函数,该构造函数接受“Account”类型的参数,并将所有信息复制到新实例中。效率不高,但它会达到你想要的效果。

public class AccountXtra : Account
{
    public AccountXtra(Account existingAccount) : base()
    {
        this.accountName = existingAccount.accountName;
        this.accountNumber = existingAccount.accountNumber;
        ...
    }
}

答案 2 :(得分:1)

您现在需要生成派生类的新对象,而不是基础。将旧的来电new Account替换为new AccountXtra。或者,您需要一个AccountXtra的构造函数,它接受一个Account对象并生成一个新的派生类版本:

public AccountXtra(Account baseInstance) : this()
{
    this.Field1 = baseInstance.Field1;
    this.Field2 = baseInstance.Field2;
    ...
}

说明:除非派生类属于派生类,否则不能将基类强制转换为派生类。这将有效:

AccountXtra accountXtra = new AccountXtra();
Account xtraAsBase = (Account)accountXtra;
AccountXtra xtraCastBack = (AccountXtra)xtraCastAsBase;

但这不会:

Account Base = new Account();
AccountXtra baseAsDerived = (AccountXtra)Base;  //Cast base to derived class

答案 3 :(得分:0)

您可能希望将其抽象为具有所有常见属性的公共抽象类:

public abstract class Account
{
   //all common members make them abstract
   public abstract int AccountId  { get; set; }
}

那么你的额外和一个新的“基本”帐户来自该通用帐户类吗?

public class AccountBasic : Account
{ 
   public override int AccountId  { get; set; }
   //implement the rest
}

public class AccountExtra : Account
{
   public override int AccountId  { get; set; }
   //your extra details
   public int Period { get; set; }
   public int Visitors { get; set; }
   public string ContactName { get; set; }
}

这让你有一个集合说:List allAccounts;你可以在哪里操纵共同的属性。在维护专业类的实例时。

答案 4 :(得分:0)

这是对先前答案的评论,但我想它太长了。

拥有一个带有构造函数的子类,该构造函数接受父类的实例并从中复制数据是一个相当普遍的标准。使用多级继承和其他类可以减少头痛的一种方法是创建一个受保护的函数来完成这项工作,在这种情况下我们称之为Assign。请考虑我们有三个类PersonEmployeeManager。它们各自按顺序继承。

public class Person
{
    private string name;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }

    protected void Assign(Person otherPerson)
    {
        Name = otherPerson.Name;
    }
}

现在我们定义员工:

public class Employee : Person
{
    private int employeeID;

    public Employee() { }
    public Employee(Person newEmployee) : this()
    {
        base.Assign(newEmployee);
    }

    public int EmployeeID
    {
        get { return employeeID; }
        set { employeeID = value; }
    }

    protected new void Assign(Employee otherEmployee)
    {
        base.Assign(otherEmployee);

        EmployeeID = otherEmployee.EmployeeID;
    }
}

然后我们按照Manager的相同示例:

public class Manager : Person
{
    private string department;

    public Manager() { }
    public Manager(Employee newManager) : this()
    {
        base.Assign(newManager);
    }

    public string Department
    {
        get { return department; }
        set { department = value; }
    }

    protected new void Assign(Manager otherManager)
    {
        base.Assign(otherManager);

        Department = otherManager.Department;
    }
}

因此,每个类中的Assign()方法声明new,以便我们可以更改签名,并为继承的类提供浅复制功能。

请注意,此模式会创建一个与旧对象具有相同数据的NEW对象。旧对象仍然存在,现有引用不会指向您的新对象。实际上不允许更改对象的TYPE。