Java初学6.6.2-多态的应用
多态数组:数组定义类型为父类类型,里面的保存的实际元素为子类类型。
在Java中,多态数组是一个强大的特性,它允许你定义一个数组,其元素类型为某个基类(父类),但实际存储的是该基类的子类实例。这利用了Java的向上转型(upcasting),即子类对象可以被赋值给父类引用。
下面是一个使用多态数组的例子,先定义一个基类 Animal 和两个子类 Dog 和 Cat,并且每个类都有一个 speak 方法:
public class Animal {
public void speak() {
System.out.println("Some generic animal sound");
}
}
public class Dog extends Animal {
public void speak() {
System.out.println("Woof!");
}
}
public class Cat extends Animal {
public void speak() {
System.out.println("Meow!");
}
}
接下来,可以创建一个 Animal 类型的数组,并在其中存储 Dog 和 Cat 实例:
public class Main {
public static void main(String[] args) {
Animal[] animals = new Animal[2]; // 定义一个Animal类型的数组
animals[0] = new Dog(); // 存储Dog实例
animals[1] = new Cat(); // 存储Cat实例
for (int i=0;i<animals.length;i++) {
Animals[i].speak(); // 调用speak方法,这里体现了多态性
}
}
运行上述代码,输出:
Woof!
Meow!
在这个例子中,虽然数组的声明类型是 Animal,但我们可以将 Dog 或 Cat 实例存储在数组中。当我们通过数组遍历并调用 speak 方法时,实际上调用的是每个对象的特定实现,而不是 Animal 类中的默认实现。这就是多态性的体现:相同的调用在运行时会表现出不同的行为,具体取决于对象的实际类型。
package PolyMorphicTest;
public class PolyTest0003 {
public static void main(String[] args){
PolyTest0003A[] p = new PolyTest0003A[5];
p[0] = new PolyTest0003A("与姜昆",22);
p[1] = new PolyTest0003B("帐篷非",23,59);
p[2] = new PolyTest0003B("勺子长",22,59.9);
p[3] = new PolyTest0003C("坚毅许安",23,19820);
p[4] = new PolyTest0003C("大帅哥",18,120000);
//编译类型都是PolyTest0003A,运行类型A,B,B,C,C。
/*p[0].printPolyTest0003();
p[1].printPolyTest0003();
p[2].printPolyTest0003();
p[3].printPolyTest0003();
p[4].printPolyTest0003();*/
//循环遍历数组:
for(int i=0;i<p.length;i++){
p[i].printPolyTest0003();//动态绑定机制。
}
//调用子类中的特有方法,需要使用向下转型。
if (p[1] instanceof PolyTest0003B) {
/*PolyTest0003B x = (PolyTest0003B) p[1];
x.uniquePolyTest0003B();等价于:*/
((PolyTest0003B) p[1]).uniquePolyTest0003B();
}
if (p[3] instanceof PolyTest0003C) {
((PolyTest0003C) p[3]).uniquePolyTest0003C();
}
}
}
class PolyTest0003A {
private String name;
private int age;
public PolyTest0003A(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public void printPolyTest0003() {
System.out.print(getName() +" " + getAge() + " ");
}
}
class PolyTest0003B extends PolyTest0003A {
private double score;
public PolyTest0003B(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
public void printPolyTest0003() {
super.printPolyTest0003();
System.out.println(getScore());
}
public void uniquePolyTest0003B() {
System.out.println("嘻嘻~");
}
}
class PolyTest0003C extends PolyTest0003A {
private double salary;
public PolyTest0003C(String name, int age, double salary) {
super(name, age);
this.salary = salary;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public void printPolyTest0003() {
super.printPolyTest0003();
System.out.println(getSalary());
}
public void uniquePolyTest0003C() {
System.out.println("哈哈~");
}
}
多态参数:在Java中,多态参数主要通过两种方式实现:方法重载(overloading)和方法重写(overriding)。然而,在讨论多态参数时,我们通常指的是后者,即方法重写,因为这直接涉及到对象的多态性和动态绑定。
方法重写(Overriding)实现多态参数
方法重写发生在子类中,子类可以重写(override)从父类继承的方法。这意味着子类提供了自己版本的实现,这个实现可以有不同的行为。当我们通过父类类型的引用调用一个方法时,实际执行的是由引用所指向的对象类型所定义的方法,这就是动态绑定(dynamic binding)。
class Animal {
void makeSound() {
System.out.println("Some generic sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Woof!");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Meow!");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal();
Animal myDog = new Dog();
Animal myCat = new Cat();
makeSound(myAnimal);
makeSound(myDog);
makeSound(myCat);
}
public static void makeSound(Animal animal) {
animal.makeSound();
}
}
在上述代码中,makeSound 方法是多态的,因为它接受一个 Animal 类型的参数。当我们通过 makeSound 方法传递 Dog 或 Cat 对象时,实际执行的是这些子类重写后的方法,而不是 Animal 类中的方法。这是因为Java使用动态绑定,调用哪个方法取决于运行时对象的实际类型。
package PolyMorphicTest;
public class PolyTest0004 {
public static void main(String[] args) {
NormalEmployee n = new NormalEmployee("浴巾阿坤",16000);
System.out.println(n.getSalary());
Manager m = new Manager("勺子啊擦",300,900);
System.out.println(m.getSalary());
/*PolyTest0004 polyTest0004 = new PolyTest0004();//如果一个方法不是静态的(即没有使用 static 关键字声明),那么它必须通过一个类的实例来调用。
polyTest0004.show(n);
polyTest0004.show(m);
polyTest0004.show01(n);
polyTest0004.show01(m);*/
PolyTest0004.show(n);
PolyTest0004.show(m);
PolyTest0004.show01(n);
PolyTest0004.show01(m);
}
/*public void show(PolyTest0004Employee a){
a.getSum();
}
public void show01(PolyTest0004Employee a){
if(a instanceof NormalEmployee){
((NormalEmployee) a).NormalWork();
}else if(a instanceof Manager){
((Manager) a).Manage();
}
}*/
public static void show(PolyTest0004Employee a){
a.getSum();
}
//将这些方法设置为静态的,那么在 main 方法中,不再需要创建 PolyTest0004 的实例,而是可以直接调用这些静态方法。
public static void show01(PolyTest0004Employee a){
if(a instanceof NormalEmployee){
((NormalEmployee) a).NormalWork();
} else if(a instanceof Manager){
((Manager) a).Manage();
}
}
}
class PolyTest0004Employee {
private String name;
private double salary;
public PolyTest0004Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public double getSalary() {
return salary;
}
public void setName(String name) {
this.name = name;
}
public void setSalary(double salary) {
this.salary = salary;
}
public void getSum(){
System.out.println(16 * getSalary());
}
}
class NormalEmployee extends PolyTest0004Employee {
public NormalEmployee(String name, double salary) {
super(name, salary);
}
public void getSum(){
System.out.println(getName() + ": Normal Employee Salary " + 12 * getSalary());
}
public void NormalWork(){
System.out.println("Normal Work ");
}
}
class Manager extends PolyTest0004Employee {
private double bonus;
public Manager(String name, double salary, double bonus) {
super(name, salary);
this.bonus = bonus;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
public void getSum(){
System.out.println(getName() + ": Manager Salary " + 14 * getSalary() + "+" + getBonus());
}
public void Manage(){
System.out.println("Manager Work ");
}
}