多态
多态:方法或对象具有多种形态。多态是建立在封装和继承基础之上
代码演示:方法的多态
sum方法实现了重载,method方法实现了重写;相同名称的方法有着不同的作用(形态)
public class Test {
public static void main(String[] args) {
A a = new A();
B b = new B();
a.method();
b.method();
System.out.println(b.sum(2,3));
System.out.println(b.sum(2,3,3));
}
}
class A {
public void method() {
System.out.println("父类的成员方法");
}
}
class B extends A {
@Override
public void method() {
System.out.println("子类的成员方法");
}
public static int sum(int num1,int num2) {
return num1+num2;
}
public static int sum(int num1,int num2,int num3) {
return num1+num2+num3;
}
}
对象的多态
对象多态的特点
1. 一个对象的编译类型与运行类型不同
2. 等号的左边是编译类型,等号的右边是运行类型
3. 运行期类型可能会发生变化
代码演示:对象的多态
同一个对象可以是Dog类,也可以是Cat类
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat();
animal = new Cat();
animal.eat();
}
}
class Animal {
public void eat() {
System.out.println("动物吃食物");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
}
class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
向上造型
1. 向上造型的本质:父类的引用指向子类的对象
2. 向上造型的语法:父类类型 引用名 = new 子类类型();
3. 向上造型的特点
a. 可以调用父类中所以成员(需遵守访问权限)
b. 不可以调用子类的特有的成员
c. 最终运行结果由子类的具体实现
注意:属性没有重写之说,属性的值由编译类型决定
代码演示:向上造型
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat();
animal.sleep();
}
}
class Animal {
public void sleep() {
System.out.println("动物睡觉觉");
}
public void eat() {
System.out.println("动物吃食物");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
public void run() {
System.out.println("狗在跑步");
}
}
向下转型
1. 向下转型的语法:子类类型 引用名 = (子类类型) 父类引用;
2. 向下转型的特点
a. 只能强转父类的引用,不能强转父类的对象
b. 要求父类引用必须指向的是当前目标类型的对象
c. 当向下转型后,可以调用子类类型中的所有成员
代码演示:向下转型以及instanceof关键字
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
if(animal instanceof Cat) {
Cat cat = (Cat) animal;
cat.work();
}else {
Dog dog = (Dog) animal;
dog.work();
dog.eat();
dog.sleep();
}
}
}
class Animal {
public void sleep() {
System.out.println("动物睡觉觉");
}
public void eat() {
System.out.println("动物吃食物");
}
}
class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
public void work() {
System.out.println("狗在看大门");
}
}
class Cat extends Animal {
public void work() {
System.out.println("猫在捉老鼠");
}
}
自我总结:向上转型与向下转型的区别
格式的区别
向上造型:父类类型 引用名 = new 子类类型();
向下转型:子类类型 引用名 = (子类类型) 父类的引用名;
访问的区别
向上造型:“除”子类特有的成员都能访问
向下转型:父子类的成员都能访问
(注意:权限修饰符)
Java的动态绑定机制
当调用对象方法时,该方法和该对象的内存地址/运行类型绑定
当调用对象属性时,没有动态绑定机制,哪里声明,哪里使用
代码演示:动态绑定机制
public class Test {
public static void main(String[] args) {
A a = new B();
System.out.println(a.sum());
System.out.println(a.sum1());
}
}
class A {
public int i = 10;
public int getI() {
return i;
}
public int sum() {
return getI() + 40;
}
public int sum1() {
return i + 30;
}
}
class B extends A {
public int i = 20;
public int getI() {
return i;
}
}
代码演示:多态数组
代码将近百行,里面写了哪些内容呢???
1. 四个类:父类Person、子类Student和Teacher以及测试类(两个子类都继承了父类)
2. 父类具有姓名与年龄的共同属性,学生类与老师类分别具有分数与薪资的特有属性
3. 创建多态数组,通过向上造型的方式将每个对象的属性进行赋值并访问
4. 通过向下转型的方式将访问运行类型特有的成员方法
public class Test {
public static void main(String[] args) {
Person[] persons = new Person[5];
persons[0] = new Person("赵四", 23);
persons[1] = new Student("小华", 23, 100);
persons[2] = new Student("小明", 12, 10);
persons[3] = new Teacher("老张", 28, 3000);
persons[4] = new Teacher("老陈", 26, 2000);
for (int i = 0; i < persons.length; i++) {
System.out.println(persons[i].say());
if (persons[i] instanceof Student) {
Student s = (Student) persons[i];
s.study();
} else if (persons[i] instanceof Teacher) {
((Teacher) persons[i]).teach();
} else if (persons[i] instanceof Person) {
} else {
System.out.println("类型有误,自行解决");
}
}
}
}
class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String say() {
return getName() + "\t" + getAge();
}
}
class Student extends Person {
private double score;
public Student(String name, int age, double score) {
super(name, age);
this.score = score;
}
public double getScore() {
return score;
}
@Override
public String say() {
return "学生" + super.say() + " 分数:" + getScore();
}
public void study() {
System.out.println("学生 " + getName() + "在学java...");
}
}
class Teacher extends Person {
private int salary;
public Teacher(String name, int age, int salary) {
super(name, age);
this.salary = salary;
}
public int getSalary() {
return salary;
}
@Override
public String say() {
return "老师 " + super.say() + " 薪资:" + getSalary();
}
public void teach() {
System.out.println("老师:" + getName() + ",在教java...");
}
}
代码演示:多态参数
多态数组:方法定义的形参类型是父类类型,实参类型是子类类型
将近百行代码,里面写了哪些内容呢???
1. 一共有四个类分别是父类(Employee),子类(Manager、Worker),测试类(Test)
2. 员工类的私有属性name和salary,计算年工资getAnnual方法
3. 经理类特有属性奖金bonus和管理manage方法
4. 员工类特有方法work
5. 测试类中有showEmpAnnal(Employee e)的方法,获取员工的年薪
6. 测试类中另一个testWork(Employee e)的方法,分别调用经理的管理方法和员工工作的方法
对于个人易错点,没有将5和6理解清楚,导致无法以向上造型与向下转型的方式进行调用方法
public class Test {
public static void main(String[] args) {
Worker worker = new Worker("强哥", 3000);
Manager manager = new Manager("小赵", 20000, 6000);
Test test = new Test();
test.showEmpAnnual(worker);
test.showEmpAnnual(manager);
test.testWork(worker);
test.testWork(manager);
}
public void showEmpAnnual(Employee e) {
System.out.println(e.getAnnual());
}
public void testWork(Employee e) {
if (e instanceof Worker) {
((Worker) e).work();
} else if (e instanceof Manager) {
((Manager) e).work();
} else {
System.out.println("对象有误");
}
}
}
class Employee {
private String name;
private int salary;
public Employee(String name, int salary) {
this.name = name;
this.salary = salary;
}
public String getName() {
return name;
}
public int getSalary() {
return salary;
}
public int getAnnual() {
return getSalary() * 12;
}
}
class Worker extends Employee {
public Worker(String name, int salary) {
super(name, salary);
}
public void work() {
System.out.println("工人:" + getName() + ",正在搬砖");
}
@Override
public int getAnnual() {
return super.getAnnual();
}
}
class Manager extends Employee {
private int bonus;
public Manager(String name, int salary, int bonus) {
super(name, salary);
this.bonus = bonus;
}
public int getBonus() {
return bonus;
}
public void work() {
System.out.println("经理:" + getName() + ",正在监工");
}
@Override
public int getAnnual() {
return super.getAnnual() + getBonus();
}
}
`
|