多态的概述及其代码体现
多态(polymorphic)的概述
- 事物存在的多种形态
多态的前提
- 要有继承关系
- 要有方法重写
- 要有父类引用指向子类对象
class Demo1_Polimorphic{
public static void main(String[] args){
Cat c =new Cat();
c.eat();
Animal a=new Cat();
a.eat();
}
}
class Animal {
public void eat(){
System.out.println("动物吃饭");
}
}
class Cat extends Animal{
public void eat(){
System.print("猫吃鱼");
}
}
多态中的成员访问特点
成员变量
==编译看左边(父类),运行看左边(父类)==
class Demo2_Polymorphic {
public static void main(String[] args){
Father f=new Son();
System.out.println(f.num);
}
}
class Father{
int num=10;
}
class Son extends Father{
int num=20;
}
成员方法
==编译看左边(父类),运行看右边(子类)(动态绑定)==
静态成员方法
==编译看左边(父类),运行看右边(子类)==
(静态和类相关,关不上重写,所以访问还是看左边)
只有非静态的成员方法编译看左边,运行看右边
超人的故事
class Demo3_SuperMan{
public static void main(String[] args){
Person p=new SuperMan();
System.out.println(p.name);
p.谈生意();
SuperMan sm=(SuperMan)p; //向下转型
sm.fly();
}
}
class Person {
String name = "John";
public void 谈生意(){
System.out.println("谈生意");
}
}
class SuperMan extends Person {
String name="superMan";
public void 谈生意(){
System.out.println("谈几个亿的大单子");
}
public void fly(){
System.out.println("飞出去救人");
}
}
多态向上转型和向下转型
- Person p= new SuperMan(); 向上转型
- SuperMan sm=(SuperMan)p; 向下转型
多态的好处和弊端
多态的好处
- 提高了代码的维护性(继承保证)
- 提高了代码的扩展性(多态保证)
public static void main(String[] args){
//Cat c1=new Cat();
//c1.eat();
method(new cat());
method(new cat());
//Animal a=new Cat(); 开发的是很少在创建对象的时候用父类引用指向子类对象,直接创建子类对象
}
//Cat c=new Dog(); 狗是一只猫,这是错误的
/*public static void method(Cat c){
c.eat();
}
public static void method(Dog d){
d.eat();
}*/
//如果把狗强转成猫就会出现类型转换异常ClassCastException
public static void method(Animal a){
//当做参数的时候用多态最好,因为扩展性强
// 关键字instanceof 判断前边的引用是否是后边的数据类型
if(a instanceof Cat){
Cat c=(Cat)a;
c.eat();
c.catchMouse();
}else if(a intanceof Dog){
Dog d=(Dog)a;
d.eat();
d.lookHome();
}else{
a.eat();
}
}
class Animal{
public void eat(){
System.out.print("动物吃饭");
}
}
class Cat extends Animal{
public void eat(){
System.out.println("猫吃鱼");
}
public void catchMouse(){
System.out.println("抓老鼠");
}
}
class Dog extends Animal{
public void eat(){
System.out.println("狗吃肉");
}
public void lookdog(){
System.out.println("看门");
}
}
==开发的时候很少在创建对象的时候用父类引用指向子类对象,直接创建子类对象更方便,可以使用子类对象中的特有属性和行为==
==当做参数的时候用多态最好,因为扩展性强==
如果把狗强转成猫就会出现类型转换异常,ClassCastException
案例演示
- 多态的好处
- 可以当做形式参数,可以接收任意子类对象
多态的弊端
- 不能使用子类的特有属性和行为
案例演示
关键字 instanceof 判断前边的引用是否是后边的数据类型
public static void method(Animal a){
if(a instanceof Cat){
Cat c=(Cat)a;
c.eat();
c.catchMouse();
}else if(a instanceof Dog){
Dog d=(Dog)a;
d.eat();
d.lookHome();
}else{
a.eat();
}
}
抽象类的概述及其特点
- 抽象类概述
抽象类的特点
class Demo1_Abstract{
public static void main(String[] args){
/*Animal a=new Animal();
错误Animal是抽象的,无法实例化*/
Animal a=new Cat();
a.eat();
}
}
abstract class Animal{
public class Animal{
public abstract void eat();
}
}
抽象类和抽象方法必须用abstract关键字修饰
- abstract class 类名{}
- public abstract void eat();
abstract class Animal{
public abstract void eat();
}
抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或接口;
抽象类不能实例化,那么抽象类如何应用?
- 按照多态的方式,由具体子类实例化.其实这也是一种多态,抽象类多态
抽象类的子类
- 要么是抽象类
- 要么重写抽象类中所有的抽象方法
抽象类成员的特点
- 成员变量: 既可以是变量,又可以是常量.abstract不可以修饰成员变量
- 构造方法: 有
- 用于子类访问父类数据的初始化
- 案例演示
- 抽象类的成员方法特性
- 抽象方法 强制要求子类做事情
- 非抽象方法 子类继承的事情,提高代码复用性
- 猫狗案例
class Test1_Animal{
public static void main(String[] args){
Cat c=new Cat("加菲",8);
System.out.println(c.getName()+"..."+
c.getAge);
c.eat();
c.catchMouse();
Dog d=new Dog("八公",30);
System.out.println(d.getName()+"..."+
d.getAge);
d.eat();
d.lookHome();
}
}
/*
案例演示
具体事务: 猫 狗
共 性: 姓名 年龄 吃饭
猫的特性: 抓老鼠
狗的特性: 看家
*/
Abstract class Animal{
private String name; //姓名
private int age; //年龄
public Animal(){} //空参
public Animal(String name,int age){
//有参
this.name=name;
this.age=age;
}
public void setName(String name){
this.name=name; //设置姓名
}
public String getName(){
return name; //获取姓名
}
public void setAge(int age){
this.age=age; //设置年龄
}
public int getAge(){
return age; //获取年龄
}
public abstract void eat(); //吃饭
}
class Cat extends Animal{
public Cat(){} //空参
public Cat(String name,int age){
super(name,age);
}
public abstract void eat(){
System.out.println("猫吃鱼");
}
public void catchNouse(){
System.out.prinrln("抓老鼠");
}
}
class Dog extends Animal{
public Dog(){} //空参
public Dog(String name,int age){
super(name,age);
}
public abstract void eat(){
System.out.println("狗吃肉");
}
public void lookHome(){
System.out.prinrln("看家");
}
}
葵花宝典
class Demo3_葵花宝典{
public static void main(String[] args){
岳不群 小岳子=new 岳不群();
小岳子.自宫();
}
}
abstract class 葵花宝典{
public abstract void 自宫();
}
class 岳不群 extends 葵花宝典{
public void 自宫(){
System.out.println("牙签");
}
}
class 林平之 extends 葵花宝典{
public void 自宫(){
System.out.println("用指甲刀");
}
}
class 东方不败 extends 葵花宝典{
public void 自宫(){
System.out.println("用锤子,不忍直视");
}
}
面试题
- 一个抽象类如果没有抽象方法,可不可以定义为抽象类?有什么意义?
- 可以,这么做的目的只有一个,就是不让其他类创建本类对象,交给子类完成
- abstract不能和哪些关键字共存
- static 被abstract修饰的方法没有方法体,被static修饰的可以用类名.调用,但类名.调用抽象方法是没有意义的
- final 被abstract修饰的方法强制子类重写,final不让子类重写,而这矛盾
- private abstract修饰是为了让子类看到并重写,private不让子类访问,所以他俩是矛盾的
接口的概述及其特点
接口的概述
- 从狭义角度讲就是java中的interface
- 从广义角度讲对外提供规则的都是接口
接口用关键字interface表示
- interface 接口名{}
类实现接口用implements表示
- class 类名 implements 接口名{}
接口不能实例化
- 如何实例化?按照多态的方式来实例化
接口的子类
- 可以是抽象类,但意义不大
- 可以使具体类,要重写接口中所有的抽象方法
class Demo1_Interface{
public static void main(String[] args){
//Inter i=new Inter();
接口不能被实例化,因为调用抽象方法无意义
Inter i=new Demo();
i.print();
}
}
interface Inter{
public abstract void print();
}
class Demo implement Inter{
public void print(){
System.out.println("print");
}
}
接口成员特点
成员变量
- 只能是常量,并且是静态的公共的
interface Inter{
(public static final) int num=10;
}
class Demo implements Inter{
public void print(){
num=20; //错误
System.out.println(num);
}
}
- 默认修饰符: public static final
- 建议自己手动给出
构造方法
- 接口没有构造方法
成员方法
- 只能是抽象方法
- 默认修饰符:public abstract
- 建议手动给出
类与类,类与接口,接口与接口之间的关系
- 类与类: 继承关系,只能单继承,可以多层继承
- 类与接口: 实现关系可以单实现,也可以多实现;并且还可以继承一个类的同时实现多个接口
- 接口与接口: 继承关系,可以单继承,也可以多继承
抽象类和接口的区别
成员区别
- 抽象类
- 成员变量:可以变量,也可以常量
- 构造方法:有
- 成员方法:可以抽象,也可以非抽象
- 接口
- 成员变量:只可以市常量
- 构造方法:无
- 成员方法:只可以抽象
关系区别
- 类与类:继承,单继承
- 类与接口:单实现,多实现
- 接口与接口:继承
class Demo3_Interface{
public static void main(String[] args){
System.out.println("Hello World");
}
}
interface InterA{
public abstract void printA()
}
interface InterB{
public abstract void printB()
}
//class Demo implements InterA,implements InterB{}
//这么做不允许,是非法的
class Demo implements InterA,InterB{
public void printA(){
System.out.println("printA");
}
public void printB(){
System.out.println("printB");
}
}
//interface InterC implements InterB{}
//错误 接口不能继承实现接口
interface InterC extends InterB,InterA{}
设计理念区别
- 抽象类 被继承体现的是:”is a”的关系,抽象类中定义的是该集成体系的共性功能
- 接口 被实现体现的是:”like a”的关系,接口中定义的是该继承体系的扩展功能
抽象类猫狗案例
class Test1_Animal{
public static void main(String[] args){
Cat c=new Cat("加菲",8);
c.eat();
c.sleep();
JumpCat jc=new JumpCat("跳高猫",3);
jc.eat();
jc.sleep();
jc.jump();
}
}
/*
案例演示
动物类:姓名 年龄 吃饭 睡觉
猫和狗
动物培训接口:调高
*/
abstract class Animal{
private String name; //姓名
private int age; //年龄
public Animal(){} //空参构造
public Animal(String name,int age){
//有参构造
this.name=name;
this.age=age;
}
public void setName(String name){
this.name=name; //设置姓名
}
public string getName(){
return name; //获取姓名
}
public void setAge(int age){
this.age=age; //设置年龄
}
public int getAge(){
return age; //获取年龄
}
public abstract void eat();
public abstract void sleep();
}
interface Jumping{
public void jump(); //跳高的接口
}
class Cat extends Animal {
public Cat(){} //空参
public Cat(String name,int age){
super(name,age); //有参
}
public void eat(){
System.out.println("猫吃鱼");
}
public void sleep(){
System.out.println("侧着睡");
}
}
class JumpCat extends Cat implements Jumping{
public Animal(){} //空参构造
public Animal(String name,int age){
super(name,age)
}
public void jump(){
System.out.println("猫跳高");
}
}