面向对象_多态
in Java with 0 comment

面向对象_多态

in Java with 0 comment

多态性

概念

  1. 对象的多态性:父类的引用指向子类的对象
  2. 理解多态性:一个事物的多种形态
  3. 多态的使用,虚拟方法的调用
    1. 子类中定义了与父类同名同参数的方法,在多态的情况下,此时父类的方法为虚拟方法,父类根据赋给他的不同子类对象,动态调用属于子类的该方法。这样的方法在编译器是无法确定的。
    2. 有了对象多态性以后,在编译期,只能调用父类中声明的方法;在运行期,我们实际执行的是子类重写父类的方法
    3. 总结:编译看右边,执行看左边。
  4. 多态性的使用前提:
    1. 类的继承
    2. 子类重写父类的方法。
  5. 对象的多态性,只适用于方法,不适用于属性。
  6. 多态性是运行时行为,不是编译时行为。

举例1

准备

创建一个Person类,声明公开的nameidage属性,提供eat()walk()方法。
创建Man类继承Person类,提供isSmokingid属性和重写父类方法,独有sleep()方法
创建Woman类继承Person类,提供属性packageNum属性和重写父类方法,独有goShopping()方法

public class Person {
	String name;
	int age;
   int id = 1001;//身份证号

	public void eat() {
		System.out.println("人吃饭");
	}

	public void walk() {
		System.out.println("人说话");
	}
}
public class Man extends Person {
	boolean isSmoking;
   int id = 1002;//工号
	@Override
	public void eat() {
		System.out.println("男人赚钱养家,多吃饭");
	}

	@Override
	public void walk() {
		System.out.println("男人声音粗犷");
	}

	public void sleep() {
		System.out.println("男人少睡觉,多干活");
	}
}
public class Woman extends Person {
	int packageNum;

	@Override
	public void eat() {
		System.out.println("女人减肥:少吃饭");
	}

	@Override
	public void walk() {
		System.out.println("女人细声细语");
	}

	public void goShopping() {
		System.out.println("女人逛街购物");
	}
}

练习1

创建多态,格式:父类 名称 = new 子类()

		// 多态
		Person p1 = new Man();
		p1.age = 24;
		p1.name = "王哈哈";
		p1.eat();
		p1.walk();

20200813101353

练习2

通过多态,调用子类的特有方法和属性。

      p1.isSmoking = false;
		p1.sleep();

20200813102405

练习3

在子类(Man)和父类(Person)都有一个id的属性,通过父类引用子类对象,查看调用的是哪一个id

      System.out.println(p1.id);

20200813103058

举例2

//考查多态的笔试题目:
public class InterviewTest1 {

	public static void main(String[] args) {
		Base1 base = new Sub1();
		base.add(1, 2, 3);

		Sub1 s = (Sub1)base;
		s.add(1,2,3);
	}
}

class Base1 {
	public void add(int a, int... arr) {
		System.out.println("base1");
	}
}

class Sub1 extends Base1 {

	public void add(int a, int[] arr) {
		System.out.println("sub_1");
	}

	public void add(int a, int b, int c) {
		System.out.println("sub_2");
	}

}
/*
*sub_1
*sub_2
*/

关键字 instanceof

引出

在使用多态的时候,想调用子类的独有属性和方法,那该如何实现呢?(通过上面的案例继续编写)
答:强制类型转换

20200813105508

//使用强制类型转换,可以调用子类对象的内容
		Man m1 = (Man) p1;
		m1.isSmoking = false;
		m1.sleep();

20200813104027

但是随之而来的问题就出来了,如果不小心强制转换错误,会导致异常。

      // 强制类型转换可能存在异常
		Woman w1 = (Woman) p1;
		w1.packageNum = 10;

20200813104222
类型转换异常。因为p1引用的子类对象是Man类型的,所以强制转换成Woman会引发异常。

解决办法就是通过instanceof

概念

举例1

通过上面的案例继续编写

		// 优雅的判断强转
		if (p1 instanceof Woman) {
			System.out.println("*****Woman*****");
			Woman w2 = (Woman) p1;
			w2.packageNum = 10;
		}

		if (p1 instanceof Man) {
			System.out.println("*****Man*****");
			Man m2 = (Man) p1;
			m2.isSmoking = false;
			m2.sleep();
		}

20200813104719

举例2

判断类型为直接父类或间接父类

		if (p1 instanceof Person) {
			System.out.println("*****Person*****");
		}
		
		if (p1 instanceof Object) {
			System.out.println("*****Object*****");
		}

20200813105048

面试题

class Base {
	int count = 10;

	public void display() {
		System.out.println(this.count);
	}
}

class Sub extends Base {
	int count = 20;

	public void display() {
		System.out.println(this.count);
	}
}

public class FieldMethodTest {
	public static void main(String[] args) {
		Sub s = new Sub();
		System.out.println(s.count);//20
		s.display();//20
		
		Base b = s;//多态性
		//==:对于引用数据类型来讲,比较的是两个引用数据类型变量的地址值是否相同
		System.out.println(b == s);//true
		System.out.println(b.count);//10
		b.display();//20
	}
}

Day12问题

  1. 什么是多态性?什么是虚拟方法调用?
    • 多态性:父类的引用指向子类的对象
      • 举例:Person p = new Man()
    • 虚拟方法调用:子类中定义了与父类相同方法名、相同参数的方法。在多态的情况下,此时父类的方法为虚拟方法,父类根据赋予他的不同子类对象,动态调用属于子类的该方法。
  2. 一个类可以有几个父类?一个父类可以有几个子类?子类能获取直接父类中的结构吗?子类能否获取父类中private权限的属性和方法?
    • 一个类只能有一个父类
    • 一个父类可以有N个子类
    • 可以直接获取父类中的结构
    • 能够获取到,只不过收封装性的影响,无法直接调用。
  3. 方法的重写具体规则有哪些?
    • 同名、同参数列表
    • 权限修饰符
    • 返回值类型:
      • void:父类为void,子类为void
      • 引用数据类型:父类为A类型,子类为A类型或者A类型的子类。
      • 基本数据类型:父类为int类型,子类为int类型。
    • 异常
  4. super调用构造器,有哪些具体的注意点
    • 必须在首行
  5. 在下面代码结构中:使用关键字:this,super方法的重写;继承。
    20200812141650