在我的示例中,继承发生了什么?那么,c#的正确术语是什么?

在我的示例中,继承发生了什么?那么,c#的正确术语是什么?,c#,oop,C#,Oop,我正在学习OOP,对下面的代码到底发生了什么有疑问 我有经典的狗动物例子狗继承动物 public class Animal { public string Name { get; set; } public virtual string Speak() { return "Animal Speak"; } public string Hungry() { return this.Speak(); } }

我正在学习OOP,对下面的代码到底发生了什么有疑问

我有经典的
动物
例子<代码>狗继承
动物

public class Animal
{
    public string Name { get; set; }

    public virtual string Speak()
    {
        return "Animal Speak";
    }

    public string Hungry()
    {
        return this.Speak();
    }
}


public class Dog : Animal
{
    public override string Speak()
    {
        return "Dog Speak";
    }

    public string Fetch()
    {
        return "Fetch";
    }
}
这两个问题都是基于这个作业:
animala=新狗()

  • 当我声明一个
    动物
    并将其设置为
    引用时,实际发生了什么。有专门的术语吗
  • 当我调用
    a.Hungry()
    时,输出是“Dog Speak”。如果输出是“Dog Speak”,为什么我不能调用
    a.Fetch()
    ?这里发生的事情的术语是什么
  • 如果您能提供帮助并进一步阅读,我们将不胜感激

  • 您正在将类型为
    Dog
    的对象存储在一个变量中,该变量将接受任何
    动物
    。这被称为(实际上并没有看到Servy的评论)
  • 您只能通过首先将对象投射给狗来调用fetch
  • 像这样:

    Dog dog = (Dog)a;
    dog.Fetch();
    
    否则,就编译器所知,它可能是任何动物,并且并非所有动物都有方法
    Fetch
    。还要注意的是,如果不是一个
    对象,施法者会抛出一个
    InvalidCastError

  • a
    是一个
    动物
    参考,它指向一个
    对象。这是多态性的一种形式(子类型多态性)

  • 您不能调用
    a.Fetch
    ,因为
    a
    具有类型
    Animal
    ,并且
    Fetch
    方法未在
    Animal
    类中定义

  • 这是一个“向上投射”。在C#中,存在从任何类型到其任何基本类型的隐式转换,因此您不需要做任何事情来将
    视为
    动物
    。(感谢Matt Burland提醒我这是一个合适的术语。)
  • 因为变量的类型是
    Animal
    ,因此您只能访问编译器知道
    Animal
    可以访问的成员,即
    Speak
    hunger
    。它不知道
    动物
    ,因此无法调用
    获取
    。变量的类型必须是
    Dog
    ,才能调用
    Fetch

  • 这个词就是多态性

  • 因为您的动物恰好被实例化为
    ,它将执行
    的所有方法。
    Animal
    Dog
    都有一个
    Speak
    方法,而
    Dog
    Animal
    继承
    饥饿的
    Dog
    方法重写
    动物的
    ,所以执行的就是这个

  • 无法编写
    a.Fetch
    的原因是编译器在设计时不知道这一点

  • 比如说

    Animal a;
    
    if(console.ReadLine() == "Dog")
    {
        a = new Dog();
    }
    else
    {
        a = new Animal();
    }
    
    a.Fetch();
    

    此时,当您调用
    a.Fetch
    时,您不知道a是否是狗

    如果您使用狗创建动物,您只创建了一个动物,并且只有动物的属性。原因很简单。举个例子:

    public class Animal
    {
        public string Name { get; set; }
    
        public virtual string Speak()
        {
            return "Animal Speak";
        }
    
        public string Hungry()
        {
            return this.Speak();
        }
    }
    
    
    public class Dog : Animal
    {
        public override string Speak()
        {
            return "Dog Speak";
        }
    
        public string Fetch()
        {
            return "Fetch";
        }
    }
    
    public class Cat: Animal
    {
        public override string Speak()
        {
            return "Cat Speak";
        }
    
        public string Fetch()
        {
            return "Fetch";
        }
    }
    
    所以如果你现在像这样把一个疯子关起来:

    Animal a = new Dog();
    
    你知道你的动物会说话,他饿了,你只需要知道,你可以调用
    a.Speak()
    ,你的动物会返回
    “Dog Speak”
    buf,如果你现在这样更改a:
    a=new Cat()
    你也可以调用
    a.Speak()
    ,但它会返回其他东西。。。相同的呼叫但不同的返回。当然,如果您确定动物真的是一只狗,那么您可以将其返回到显式实现

    var d= new Dog();
    if(a is Dog)
    d = a as Dog;
    
    d现在是一只真正的狗,可以做任何只有狗才能做的事情,但你不能再把d指定为猫了。因为它是狗而不是动物

    他在向上投射。您正在创建一个
    Dog
    对象,并将其分配给父类的变量。这是允许的,但是

    a.Fetch();
    
    不行。为什么,因为
    Animal
    没有名为
    Fetch
    的方法,而且据编译器所知,
    a
    可以是任何
    Animal
    。如果您想调用
    Fetch
    ,您需要将
    a
    转换回
    Dog

    Dog d = (Dog)a;
    d.Fetch();
    
    但是请注意,如果
    a
    不是
    Dog
    ,这将导致错误,因此通常先检查:

    if (a is Dog) 
    {
        Dog d = (Dog)a;
        d.Fetch();
    }
    
    当你打电话的时候

    a.Hungry();
    
    这是允许的,因为
    动物
    有一个
    饥饿
    方法。饥饿的
    方法称为
    Speak
    ,但由于
    a
    是一只
    Dog
    ,而不是基本的
    Animal
    ,它将称为
    Dog.Speak
    方法(正如Servy在其他地方指出的那样,这是真正的多态性——调用特定方法时执行的实际代码会根据对象的实际类型而有所不同)

  • 当您声明一个
    动物
    并将其设置为
    时,隐式强制转换完成
  • 请尝试此代码以查看使用
    virtual
    和不使用它的效果
  • :


    对#1而言,这并不完全是多态性。多态性是指在类型
    动物的定义中调用
    a
    的方法可能无法实现,它可以(在本例中,是)执行派生类型中定义的方法。因此,在<代码>动物<代码>中对<代码>狗<代码>进行攻击的能力不是多态性,事实上<代码>说话<代码>的结果是<代码>“狗说话”
    ,这是多态性。如果该方法不是虚拟的,它就不会是多态性的,因此会说<代码>“动物说话”
    ,但你仍然可以将
    放入
    动物
    变量中,而不使用多态性。有趣的是,我实际上认为这是多态性一词的正确用法,谢谢你提供的信息。每天学习新的东西!这实际上是
    a.Hungry();
    
    public class Animal
    {
        public string Name { get; set; }
        public string Speak()
        {
            return "Animal Speak";
        }
        public string Hungry()
        {
            return this.Speak();
        }
    }
    
    public class Dog : Animal
    {
        public new string Speak()
        {
            return "Dog Speak";
        }
        public string Fetch()
        {
            return "Fetch";
        }
    }
    
    static void Main(string[] args)
    {
        Animal a = new Dog();
        Console.WriteLine(a.Hungry());   //Animal Speak
        Console.ReadLine();
    }