Java基础——多态(继承多态、接口多态)

多态

多态的概念

定义

多态 polymorphism :对象根据所接收的消息而做出动作,同样的消息为不同的对象接收时可导致完全不同的行动,该现象 称为多态性

静态绑定

编译时多态 指在编译程序时就根据调用方法提供的信息,把它所对应的具体方法确定下来。即 在编译时就把调用方法名与具体方法绑定在一起方法重载

动态绑定

运行时多态 指在编译程序时还不能确定方法调用所对应的具体方法,只有在程序运行过程中才能确定具体的方法。 即 在程序运行时才把调用方法名与具体方法绑定在一起继承多态、接口多态

为何需要多态?

  1. 在设计一个程序系统时,可以通过在abstract类中声明若干
    abstract方法,表明这些方法在整个系统设计中的重要性,方法体的内容细节由它的非abstract子类去完成
  2. 使用多态进行程序设计的核心技术之一是使用向上转型对象,即 abstract类声明对象作为其子类的向上转型对象,那么这个向上转型对象就可以调用子类重写的方法
  3. 当将absctract类声明对象按需实际引用不同的子类对象时,就能达到以一变应万变的目的
  4. 所谓面向抽象编程,是指当设计某种重要的类时,不让该类面向
    具体的类,而是面向抽象类,即所设计类中的重要数据是抽象类声明的对象,而不是具体类声明的对象

在这里插入图片描述

继承与多态

继承基本概念

继承: 以存在的类为基础定义新的类,新类即拥有基类的数据成员和成员方法。

继承的目的: 代码重用(减少代码重复编写 code reuse)

继承的本质: 描述自然界中广泛存在的一种关系——类属关系(is-a)

实现过程:(略)

使用 extends 关键字

方法重写 Override

注意

  1. 子类重写的方法的权限不能低于父类方法的访问权限
  2. 子类重写的方法不能抛出比父类方法抛出的异常多
  3. 被重写的父子类方法须同时为static的,或同时为非static的静态方法按类绑定,实例方法按实际所引用的对象实例绑定
  4. 父类的private方法不能被重写,本质上它不是为了继承而生
  5. 重写和重载区别:重载(overload)是形式参数列表丌一样.重写 则是方法头部( 包括形式参数列表)要一致;重写只能出现在继承过程中.
  6. 对象调用被重写的非静态方法时,使用对象引用实际引用的实 例所对应的版本(即运行时绑定

继承的构造

点击跳转

父类对象引用子类实例(重点)

Java运行时某个类型的引用变量引用其子类的实例,而且可以对这个引用变量进行类型转换

简单的记: b = d;

在这里插入图片描述

继承的多态所需的三个条件:

  1. 继承 子类继承基类
  2. 重写 子类重写基类同名同参方法
  3. 父类对象引用子类实例 b = d

实例一:

// 基础版多态
class Person {
	public String toString() {
		return "Person";// 重写Object的toString方法
	}
}
class Man extends Person {
	public String toString() {
		return "Man";// 重写父类的toString方法
	}
	public void show() {
		System.out.println("这是子类独有的方法");// 子类新加的方法
	}
}
public class Test_extends_poly1 {
	public static void main(String[] args) {
		
		/*---编译时多态--- */ 
		 Person q = new Person();// b = b
		 Man m = new Man(); // d = d
		 System.out.println(q.toString());// 执行自己的方法 Person
		 System.out.println(m.toString());// 执行自己的方法 Man
		 
		 /*---运行时多态--- */ 
		 Person p = new Man(); // b = d  父类对象引用子类实例
		 System.out.println(p.toString());// 运行时多态
		 /*
		   Java从实例所属的类开始寻找匹配的方法执行
		   如果当前类没有重写匹配的方法,则沿着继承关系逐级向上寻找
		   直到Object类为止
		  */
		 p.show(); // 编译Error:**The method show() is undefined for the type Person**
		 // 编译阶段,p的类型是Person,其中没有show方法,编译不通过
	}
}
/*
	输出的结果为:
	Person
	Man
	Man
*/

实例二:

// 进阶版多态
class A {
	public String show(A obj) {
		return ("AA") ;
	}
	public String show(D obj) {
		return ("AD") ;
	}
}
class B extends A {
	public String show(A obj) {
		return ("BA");
	}
	public String show(B obj) {
		return ("BB");
	}
}
class C extends B {
	
}
class D extends B {
	
}
public class Test_extends_poly2 {
	public static void main(String[] args) {
		A a1 = new A();
		A a2 = new B();
		B b = new B();
		C c = new C();
		D d = new D();
		System.out.println(a1.show(b));// 向上转型
		System.out.println(a1.show(c));// 向上转型
		System.out.println(a1.show(d));// 向上转型
		System.out.println(a2.show(b));
		System.out.println(a2.show(c)); 
		System.out.println(a2.show(d)); 
		System.out.println(b.show(b));  
		System.out.println(b.show(c));  
		System.out.println(b.show(d)); 
	}
}

结果:
	AA 
	AA 
	AD 
	BA 
	BA 
	AD 
	BB 
	BB 
	AD 

规则:

  1. 运行时绑定:实例方法与引用变量实际引用的对象的方法
  2. 编译时绑定静态方法与引用变量所声明的类型的方法
  3. 编译时绑定成员变量(包括静态变量和实例变量)与引用变量所声明的类型成员变量

在这里插入图片描述

(俗称:编译看左边,运行看右边)

接口与多态

接口基本概念

接口是一种特殊的引用类型,没有构造方法,也不能被实例化

传统接口的接口体仅能包含两样:

  1. 公开的静态常量: 隐式 public static final 修饰组合,且必须显式初始化
  2. 公开的抽象方法: 隐式 public abstract 修饰组合

实现过程:(略)

使用 implements 关键字

接口和继承的区别

区别
抽象类1.对行为和属性的抽象,是多个类(对象)共同的抽象
2.可视作"“类模板”:使用-个抽象类派生的各子类,是有共性的
3.抽象类的各子类,都是抽象类的对象,继承抽象类的子类和抽象
4.类是一种is-A关系
接口1.对行为(动作/方法)的抽象,不是对一类事物的抽象,属协议规范
2.实现接口的类可以是不相关的类,只是它们都具有某种表现不同的行为而已
3.接口是让类拥有或者具备某种功能

接口实现多态(重点)

接口和实现类→接口变量引用实例类对象实例 i=o → 调用实现方法

实例:

// 先创建好一个接口
public interface Fly {
	
	public void fly() ;
	
}

// 创建接口的实现类
class Plane implements Fly {

	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("飞机用机翼飞行");
	}
	
}
class Bird implements Fly {
	
	@Override
	public void fly() {
		// TODO Auto-generated method stub
		System.out.println("小鸟用翅膀飞行");
	}
}
// 进行调试
public class Test_interface_poly1  {

	public static void main(String[] args) {
		Fly Cfly;
		Bird bird = new Bird();
		Plane plane = new Plane();
        
		Cfly = bird;// 接口引用实现类对象实例
		Cfly.fly();// 调用实现方法
        
		Cfly = plane;// 接口引用实现类对象实例
		Cfly.fly();// 调用实现方法

	}
}
/*结果:

小鸟用翅膀飞行
飞机用机翼飞行

*/

接口与匿名内部类

匿名类:用在其只用-次并简化代码的地方.
匿名类必须:要么继承一个类,要么实现一个接口.

实例:

// 使用回上述的Fly接口
// 新建一个类用于测试
public class Test_interface_poly2 {
	
	public static void main(String[] args) {
		Fly XFly = new Fly() {
			
			@Override
			public void fly() {
				// TODO Auto-generated method stub
				System.out.println("匿名类也飞了");
			}
		}; // 分号“;”不能缺少
		XFly.fly();
	}
}

构造过程实例:

public class A {
	A(int p) {
		System.out.println("带参构造子" + p);
	}

	A() {
		System.out.println("无参构造子");
	}

	void method() {
		System.out.println("fromA");
	}

	public static void main (String []args) {
		new A().method(); 
		A z = new A(){ 
			void method() { 
                System.out.println("fram 匿名类0"); 
            }
		};// 分号不可缺
		
		z.method() ;
		A a = new A(1) {}; 
		a.method() ;
		A b = new A(2) { 
			void method() { 
                System.out.println("from 匿名类2"); 
			};
		};// 分号不可少
        
		b.method();
	}
}
结果:
无参构造子
fromA
无参构造子
fram 匿名类0
带参构造子1
fromA
带参构造子2
from 匿名类2

在Java创建线程或监听器对象时,经常使用这种匿名类语法

匿名类最后必须写上“;” 因为匿名类是一种语法

资料参考:仲恺农业工程学院——信科院课程组——《面向对象程序设计(Java)》

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值