C# 面向对象编程

C# 面向对象编程,c#,C#,我是C#的新手。我有一个具有此功能的Persons类: public virtual void InputPerson(Persons P) { P.ID = int.Parse(Console.ReadLine()); Console.WriteLine("Titel:"); P.Titel = Console.ReadLine(); Console.WriteLine("Name:");

我是C#的新手。我有一个具有此功能的Persons类:

public virtual void InputPerson(Persons P)
    {           
        P.ID = int.Parse(Console.ReadLine());
        Console.WriteLine("Titel:");
        P.Titel = Console.ReadLine();
        Console.WriteLine("Name:");
        P.Name = Console.ReadLine();
        Console.WriteLine("Surname:");
        P.Surname = Console.ReadLine();         
    }
我有一个从Persons类继承的User类。我现在需要在User类中创建一个InputUser函数,该函数在Persons类中使用这个InputPerson函数,而无需重写从InputPerson函数到InputUser函数的所有代码。以下是我在InputUser函数中的代码:

public override void InputPerson(User U)
    {
        Console.WriteLine("Please enter a Customer:");
        Console.WriteLine("Customer ID:");
        base.InputPerson;
        Console.WriteLine("Telephone Number:");
        U.Telephone = int.Parse(Console.ReadLine());

        Console.WriteLine();
    }
此InputUser代码给我一个错误,说明:

'UserCustomerNotes.User.InputPerson(UserCustomerNotes.User)': no suitable method found to override
有人能帮忙吗

提前谢谢

  • base.InputPerson根本无法工作

  • 您不能用
    void InputPerson(用户U)
    覆盖
    void InputPerson(用户p)
    。签名必须相同


  • 不要重写该方法,而是使用
    new
    关键字,因为签名不同

    public new void InputPerson(User U)
    
    然后,您只需将
    用户U
    传递给基类,而不是

    base.InputPerson;
    
    使用


    要重写一个方法,必须保留它的签名,而不是(将参数的类型从Persons更改为User,所以创建一个新方法)。因此,请删除“override”关键字

    此外,使用:

    InputPerson(U);
    
    而不是:

    base.InputPerson;
    

    这只是我对这个问题的一个更切题的看法,但在面向对象设计的传统指导原则下,用户是一个人,因此你得到了继承。然而,当我们审视原则,尤其是“利斯科夫替代原则”时:

    “使用指向基类的指针或引用的函数必须能够在不知情的情况下使用派生类的对象。”-Robert Martin,LSP论文,链接自OOD原则

    这是什么意思?好的,我们应该能够用一个子类的实例替换它的父类,并且一切都应该继续工作。在这种情况下,它将不起作用,您需要为用户提供其他属性,而用户没有这些属性

    在这种情况下,您是否考虑过进行组合而不是继承

    public class Person
    {
       public static void InputPerson(Person p)
       {
          // Do the input logic here
       }
    }
    
    public class User
    {
        public Person Person { get; private set; }
    
        public static void InputUser(User u)
        {
            if (u.Person == null)
                u.Person = new Person;
            Person.InputPerson(u.Person);
            Console.WriteLine("Telephone:");
            u.Telephone = Console.ReadLine();
        }
    }
    

    我们可以进一步深入到SOLID中,看看单一责任原则,并询问Person/User对象是否处理作为人的逻辑,但它是否应该知道如何从控制台创建该对象?如果要对windows应用程序或WPF应用程序重复使用相同的逻辑,会发生什么情况?

    还可以利用类继承执行以下操作:

    public override void InputPerson(Persons P)
    {
       // Code in here
    }
    
    因为用户是Persons,所以允许您将其作为参数直接传递到方法中。然而,如果有 用户上不存在的自定义属性可以引入泛型

    public class Persons<T>
    {
       public virtual void InputPerson(T p)
       {
     // code here.
       }
    }
    
    public class User : Person<User>
    {
     public override void InputPerson(User p)
     {
      // code here. You can now treat the input as a user
      // as you have told your base class that the 'T' is a user.
     }
    }
    
    公共阶层人士
    {
    公共虚拟空输入人(TP)
    {
    //代码在这里。
    }
    }
    公共类用户:Person
    {
    公共覆盖无效InputPerson(用户p)
    {
    //在这里编码。您现在可以将输入作为用户处理
    //正如您告诉基类的那样,“T”是一个用户。
    }
    }
    
    是的,我确实认为这是我的问题。谢谢。不,他不是一个活生生的储蓄者,因为你最终会得到一个不符合逻辑的程序,除了如何修复编译错误之外,你什么也学不到。@Ondrej:但这难道不是一个比简单地被告知以另一种方式做事情,而不真正理解为什么更好的学习体验吗?你不可能一下子学会所有东西,但你甚至没有花时间解释为什么你建议的解决方案通常被视为一种强烈的气味。因此,除了帮助OP,你还鼓励他们使用糟糕的做法(甚至不给她/他一点机会),符文FS:“嗨,我是C#新手”告诉我他们才刚刚开始学习语言,我不想把他们与他们可能还没有准备好的OO设计相混淆,但这可能是错误的。如果你想向他们解释为什么这是一种不好的做法,尽管我相信他们会非常感激。那么“人”的其他用途是什么呢?你不能用一个人代替一个人,而如果他们是从一个人衍生出来的,你可以用这个代替。我想说的是,在不同类型的人之间,你在没有任何收获的情况下(你基本上是在破坏继承/关系),使事情变得更加复杂
    public class Persons<T>
    {
       public virtual void InputPerson(T p)
       {
     // code here.
       }
    }
    
    public class User : Person<User>
    {
     public override void InputPerson(User p)
     {
      // code here. You can now treat the input as a user
      // as you have told your base class that the 'T' is a user.
     }
    }