继承和多态有什么区别?

20

你能给我一个继承和多态性的简单例子吗?这样可以更加清晰易懂。

使用 C# 编程语言会更容易理解,因为我已经学过它了。

P.S: 我们得到的教材和导师都是用阿拉伯语写的。

如果你不完全理解这些概念,那么对你来说它们就很难。希望我的问题不会对你们来说太简单或者太愚蠢了。


42
这位发帖者显然不是以英语为母语的人,他请求我们帮助他理解两个在编程中被广泛使用的英语单词的区别,因为他的教材是用阿拉伯文写的。由于他不太懂英语,他希望一段以他懂的语言编写的代码能帮助他了解主要内容,而不必阅读几段英语解释。给他一些时间吧。 - StriplingWarrior
@Strip 不错的理论,但 OP 对英语有很好的掌握:http://stackoverflow.com/questions/7325073/how-could-i-get-over-my-programming-problems。 - Tim Lloyd
1
@chibacity:啊,好吧。给人们怀疑的机会就这样没了。 - StriplingWarrior
我认为,完全可以在不知道某些术语的确切定义的情况下,充分理解多态行为。 - Alex
8个回答

51

这就是多态:

public interface Animal 
{
  string Name { get; }
}

public class Dog : Animal
{
  public string Name { get { return "Dog"; } }
}

public class Cat : Animal
{
  public string Name { get { return "Cat"; } }
}

public class Test 
{
  static void Main()
  {
      // Polymorphism
      Animal animal = new Dog();

      Animal animalTwo = new Cat();

      Console.WriteLine(animal.Name);
      Console.WriteLine(animalTwo.Name);
  }
}

这是继承:

public class BaseClass
    {
        public string HelloMessage = "Hello, World!";
    }

    public class SubClass : BaseClass
    {
        public string ArbitraryMessage = "Uh, Hi!";
    }

    public class Test
    {
        static void Main()
        {
            SubClass subClass = new SubClass();

            // Inheritence
            Console.WriteLine(subClass.HelloMessage);
        }
    }

25

继承意味着如果你创建了一个拥有公共字段TankSize的Car类,那么从它派生出一个SuperCar类,后者将从Car继承字段TankSize。

多态性指的是每次在代码中需要一个Car对象的方法时,你都可以传递一个SuperCar对象,它会像一个Car一样运行。

通过定义所需的虚方法,你将调用基类上的方法,但实际操作的对象将执行其自己版本的虚方法,因此你将调用SuperCar.GetPrice而不是Car.GetPrice。

以上简要介绍,更多信息,请参见其他人正在写作的答案。


6
有时候简单的话语胜过一堂演讲,感谢你分享你清晰的思想。 - Obzajd
你的第二段是错误的,我认为。你需要交换Car和SuperCar - 每次你需要父类(SuperCar)时,你可以传入一个子类(Car)。 - Jonesopolis
@Jonesy 我非常确定他在使用通用的世界语义,SuperCar 是一辆更好、更强大的汽车。如果使用程序员的语义,那么它将成为一个 _SubCar_。 - Alex

23

让我们使用我最喜欢的动词并找到:

http://en.wikipedia.org/wiki/Polymorphism_%28computer_science%29

http://msdn.microsoft.com/en-us/library/ms173152%28v=vs.80%29.aspx

多态性和继承是C#和面向对象编程中不可或缺、需要牢记的基本概念。如果你说你懂C#但不懂这个,就好像知道如何说英语却不知道字母表一样。抱歉直言,但这是事实。

来自上面的维基链接(这不是我的),以下是多态性的一个示例(转换为C#...)

public class Animal
{
    public virtual String talk() { return "Hi"; }
    public string sing() { return "lalala"; }
}

public class Cat : Animal
{
    public override String talk() { return "Meow!"; }
}

public class Dog : Animal
{
    public override String  talk() { return "Woof!"; }
    public new string sing() { return "woofa woofa woooof"; }
}

public class CSharpExampleTestBecauseYouAskedForIt
{
    public CSharpExampleTestBecauseYouAskedForIt()
    {
        write(new Cat());
        write(new Dog());
    }

    public void write(Animal a) {
        System.Diagnostics.Debug.WriteLine(a.talk());
    }

}

11

让我们用更有趣的方式解释这个问题。 继承是派生类利用基类功能的方法。 多态是基类利用派生类实现的方法。

public class Triangle :Shape {
 public int getSides() {
  return 3;
 }
}

}
public class Shape {
 public boolean isSharp(){
  return true;
 }
 public virtual int getSides(){
  return 0 ;
 }

 public static void main() {
  Triangle tri = new Triangle();
  System.Console.WriteLine("Triangle is a type of sharp? " + tri.isSharp());  //Inheritance 
  Shape shape = new Triangle();
  System.Console.WriteLine("My shape has " + shape.getSides() + " sides.");   //Polymorphism 
 }
}

现在你说了这个,这是一个有趣的话题,我可以在日常编程中学习和使用,不再避免它。 - Obzajd

8

多态是覆盖所继承的内容。

如果你不覆盖它,那就不是多态,而只是继承。


2
除非您正在使用接口,否则您将通过接口实现多态行为。 - Todd Vance

6

继承和多态之间没有区别。多态是继承的一部分,没有继承就不能存在多态。简单来说,多态是将对象视为基类对象的能力,但从基类调用虚方法将会调用子类的适当方法。这里有一个很好的例子:http://www.psworld.pl/Programming/Inheritance


6
当你从一个基类派生出一个子类时,子类将继承基类的所有成员,除了构造函数。然而,该派生类是否能够访问这些成员将取决于基类中这些成员的可访问性。C#通过继承为我们提供了多态性。基于继承的多态性允许我们在基类中定义方法并使用派生类实现来重写它们。因此,如果您有一个基类对象,可能会保存几个派生类对象,适当使用多态性可以根据对象所属的派生类类型调用不同的方法,以实现不同的操作。
参考链接:http://www.codeproject.com/Articles/1445/Introduction-to-inheritance-polymorphism-in-C

那个最后的句子非常有帮助。 - Dan Hogan

1

这一切都与行为有关。

一个类声明了某种行为(接口或契约):

该类也可以定义该行为(实现),或将整个或部分行为委托给其任何子类:

伪代码如下:

class Animal {
    method walk()
    method speak()
    method jump()
    // ... here goes the implementation of the methods
}

通过子类化,您可以使一个类继承另一个类的行为。
当一个方法的实现被委托给子类时,在基类中该方法被称为抽象方法,在像Java这样的语言中,整个基类也变成了抽象类:
abstract class Animal {
    method walk() {
       doWalk()
    }
    method speak() {
       print "hi, I am an animal!"
    }
    abstract method jump() // delegated to specific animals
}

class Horse inherits from Animal {
    override method walk() {
        doWalkLikeAHorse()
    }
    override method speak() {
        print "hi, I am a horse!"
    }
    override method jump() { 
        doJumpLikeAHorse()
    }
}

class Elephant inherits from Animal {
    override method walk() {
        doWalkLikeAnElephant()
    }
    override method speak() {
        print "hi, I am an elephant!"
    }
    override method jump() { 
        throw error "Sorry, I can't jump!!"
    } 
}

一个类的行为默认是虚拟的,这意味着任何类方法都可以被任何子类重写。这是 C# 和 Java 等语言的工作方式,但不一定适用于 C++,例如。
实质上,基类的行为仅为虚拟,并且在子类覆盖该虚拟行为时可以假设“多个”(poly)“不同的形式”(morphs)。这就是为什么它被称为多态性。伪代码如下:
function makeAnimalSpeak(Animal animal) {
    animal.speak();
}

makeAnimalSpeak(new Elephant()) // output: "hi, I am an elephant"
makeAnimalSpeak(new Horse())  // output: "hi, I am a horse"

这里有其他人提供了更好的例子。

在像C#和Java这样的语言中,你有接口(在C++中不存在)的概念,它只是一个行为的声明。与类不同,接口没有实现行为的义务。它只是一个声明。任何类都可以实现该行为,无论它们继承自什么基类。伪代码如下:

interface FlyingBeing {
    method fly()
}

class FlyingPig inherits from Animal implements FlyingBeing {
    method fly() {
       print "hey, look at me, I am a flying pig!!"
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接