我正在研究多态性。我无法确定 Java 中关于这两个特性的类比。
假设Animal
类是一个具体的超类,它的子类是Cat
和Dog
。我知道这是一个继承的例子。Cat
但是和类不是Dog
类的多态Animal
吗?
我非常了解Java中的接口。我不明白为什么使用接口而不是具体的类来解释多态性。可能创建接口的全部目的是创建多态,但我想知道为什么是接口而不是具体类?
我正在研究多态性。我无法确定 Java 中关于这两个特性的类比。
假设Animal
类是一个具体的超类,它的子类是Cat
和Dog
。我知道这是一个继承的例子。Cat
但是和类不是Dog
类的多态Animal
吗?
我非常了解Java中的接口。我不明白为什么使用接口而不是具体的类来解释多态性。可能创建接口的全部目的是创建多态,但我想知道为什么是接口而不是具体类?
class Animal{
public void speak(){ System.out.println("Speaking something");}
}
class Person extends Animal{
@Override
public void speak(){ System.out.println("Hello..");}
}
Animal a = new Person();
a.speak();// Hello
多态性的字典定义是指生物学中的一个原理,其中一个有机体或物种可以有许多不同的形式或阶段。这个原则也可以应用于面向对象的编程和像 Java 语言这样的语言。一个类的子类可以定义自己独特的行为,但共享一些与父类相同的功能[..]
为什么是接口?
您知道需要做什么,但您希望实施者决定如何做,您将让实施者强制实施这些东西
接口使用一种类型的多态性,即方法覆盖。
接口通常用作常用方法的契约。
我不知道接口是解释多态性的最好方法。多态性是遗传的产物。从观察者的角度来看,这是在查看继承层次结构时发生的事情。每只动物都可能发出声音,但是当观察者真正观察到动物发出声音时,猫会喵喵叫,狗会吠叫。小型犬吠叫,而大型犬吠叫。多态性是使这些属性基于它们在继承层次结构中的位置隐式展示自己的能力。
接口是实现组合的一种方式。您可以将属性添加到其他相关或不相关对象可能具有或不具有的对象。这只狗是个流口水者。而猫是一个抓挠者。其他不一定属于动物继承层次结构的东西也可能具有这些流口水和/或抓挠属性。
继承在 Java 中实现为分别使用extends
or关键字对超类或接口的方法/字段进行简单扩展。implements
无论哪种方式,您都可以在子类中访问超类的公共和受保护数据成员,并且当从外部对子类进行操作时,只能访问公共数据成员。
以您的示例为例,您可以定义几个类:
class Animal {
private int location;
public Animal() {
location = 0;
}
public void move() {
location += 10;
}
public int getLocation() {
return location;
}
}
class Dog extends Animal {
@Override
public void move() {
setLocation(getLocation() + 5);
}
}
/*
* The @Override flag is optional, but I prefer to put it there
* to ensure that I am actually overriding a method or implementing
* a method from an interface.
*/
class Cat extends Animal {
@Override
public void move() {
setLocation(getLocation() + 15);
}
}
所以Dog
两者Cat
都扩展了 Animal - 这是一种继承关系。
多态性是完全不同的东西。根据维基百科:
多态性在工业中的主要用途(面向对象编程理论)是属于不同类型的对象能够响应同名的方法、字段或属性调用,每个调用都根据适当的特定于类型的行为。
用简单的英语术语来说,这只是意味着采取相同的想法或行动,并根据它是特定类型的对象以不同的方式实现它。在代码中:
public static void main(String[] args) {
Animal animalArray = {
new Animal(),
new Cat(),
new Dog()
};
for (Animal a : animalArray) {
a.move();
}
System.out.println("Animal location: " + animalArray[0].getLocation());
System.out.println("Cat location: " + animalArray[1].getLocation());
System.out.println("Dog location: " + animalArray[2].getLocation));
}
这将产生输出:
Animal location: 10
Cat location: 15
Dog location: 5
请注意,每个对象 the Animal
、 theCat
和 theDog
都作为Animal
s 访问。这是可能的,因为每个类都是或 extends Animal
,因此每个类都将始终具有 public 方法move()
,在某些情况下它只是被重新定义。
接口的工作原理相同;如果一个类扩展了一个接口,则可以保证接口中定义的每个方法都有一些实现,因此可以根据接口实现的方法来使用它。
假设您已受雇创建一种编程语言,这是要求之一:
1 > 3 should call code from the integer comparison library.
1.0 > 3.0 should call code from the floating point comparison library.
"McDonald" > "MacDonald" should call code from the locale-aware string comparison library.
该要求是“多态性”,其中相同的文本(> 运算符)根据情况(在本例中为操作数的类型)执行不同的操作。
您可以通过将整数、浮点数和字符串全部派生自同一个基类并将基类定义为具有虚拟比较运算符来满足这些要求。这可能会变得混乱。如果稍后,语言用户想要...
blue > yellow
...要编译为执行颜色操作的代码,基类方法意味着说颜色、字符串、浮点数和整数都是更通用基础的特殊情况。我认为那会很奇怪。
另一种方法是为应用程序开发人员提供一种语言方式来创建任意类型并说明它们支持哪些操作,并让库开发人员为支持一组操作的任何类型提供函数。例如,您可以为支持比较和赋值运算符的任何类型编写排序例程。
这种方法称为接口,它的优点是可以很好地处理非常不同的类型。