代码之家  ›  专栏  ›  技术社区  ›  Andrew Harry

解决继承问题

  •  2
  • Andrew Harry  · 技术社区  · 17 年前

    我希望通过一些附加功能扩展C中的基类。我有返回基类对象(account)数组的现有代码,我需要将其转换为扩展版本。

    所以我有了扩展版本:

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

    一切都好。

    但是,当我有帐户实例时,如何创建accountxtra的新实例?

    我已经尝试过:

    //This doesn't work
    AccountXtra newInstance = (AccountXtra)accountInstance;
    //This also doesn't work
    AccountXtra newInstance = new AccountXtra();
    newInstance = accountInstance;
    
    5 回复  |  直到 17 年前
        1
  •  1
  •   lc.    17 年前

    您需要生成 衍生的 现在上课,不是基础课。将旧呼叫替换为 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
    
        2
  •  1
  •   overslacked    17 年前

    但是,当我有帐户实例时,如何创建accountxtra的新实例?

    这是错误的做法-您需要创建accountxtra对象,然后可以将其作为帐户对象在任何地方进行处理。

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

    请随时用您遇到的具体问题更新您的问题。

        3
  •  1
  •   Jesse Weigert    17 年前

    不能将基类转换为子类。换句话说,如果对象的类型为“account”,则不能将其强制转换为“accountxtra”。但是,如果您有一个“accountxtra”类,因为它继承自“account”,那么您可以将它强制转换为account。

    如果已有代码的源代码,则需要更改它调用“new account()”构造函数的位置,并将其更改为“new accountxtra()”。您还应该将“account”类的实例替换为“accountxtra”。

    您可以尝试的另一个想法是在accountXtra()中创建一个构造函数,它使用类型为“account”的参数,并将所有信息复制到新实例中。不完全有效,但它会达到你想要的效果。

    public class AccountXtra : Account
    {
        public AccountXtra(Account existingAccount) : base()
        {
            this.accountName = existingAccount.accountName;
            this.accountNumber = existingAccount.accountNumber;
            ...
        }
    }
    
        4
  •  0
  •   Nick Josevski    17 年前

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

    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; }
    }
    

    这允许您拥有一个集合,比如:列出所有帐户;在这里您可以操作公共属性。同时维护专用类的实例。

        5
  •  0
  •   Adam Robinson    17 年前

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

    拥有一个带有一个父类实例并从中复制数据的构造函数的子类是一个相当普遍的标准。一种方法是创建一个受保护的函数来完成这项工作,在本例中,我们将调用它assign,从而最大限度地减少这一问题在多个继承级别和其他类中可能引起的头痛。我们有三个班, Person , Employee Manager . 他们每个人都是按照这个顺序继承的。

    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 这样我们就可以更改签名,并为继承的类提供浅复制功能。

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