面向对象-oop-7-接口、多态

  • 接口
    • 是一种数据类型(引用类型)
    • 由interface定义
    • 只能包含常量和抽象方法
    • 接口中的属性都是常量,默认由public static final同时修饰,可以省略,abstract不能修饰变量
    • 接口不能被实例化(new对象)
    • 接口是需要被实现/继承的,实现/派生类,必须重写接口中的所有抽象方法(重写时必须加public关键字)
    • 一个类可以实现多个接口,用逗号分隔,implements只用写一次, 若又继承又实现时,应先继承后实现
      • eg:class A extend B implements C,D 
      • java类是单继承的。classB Extends classA
      • java接口可以多继承。Interface1 Extends Interface2, Interface3, interface……
      • 不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个E方法,A如何决定该继承哪一个呢?
      • 但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口。
    • 接口可以继承接口,接口不能实现接口
    • 接口的方法默认都是public abstract的,也只能是public 不写会默认
    • 接口中不可以定义变量,只能定义常量,所以接口的属性默认是public static final 也只能是 ,不写会默认,返回值类型 常量,且必须赋值
    • 注意final 和abstract 不能同时出现
不能用来修饰 interface 的有(A,C,D)
A.private 
B.public 
C.protected 
D.static 


//修饰接口可以是public和默认


  • 设计规则
    • 将所有派生类所有共有的属性和行为,抽到超类中-------------抽共性
    • 派生类的行为都一样,设计普通方法
    • 派生类的行为不一样,设计为抽象方法
    • 将部分派生类所共有的属性和行为,抽到接口中
    • 接口是对继承的单根性的扩展-------------------------实现多继承
  • 多态
    • 行为的多态
      • 同一类型的引用在指向不同的对象时,有不同的实现(所有抽象方法都是多态的):
      • (比如人跑步类型:指向刘翔,刘翔110跑了12秒91,指向小翠,小翠跑了91秒21)
    • 对象的多态
      • 同一个对象被造型为不同的类型时,有不同的功能(所有对象都是多态的)
      • (有两个接口,钱接口,命接口,一个父类人。定义一个persion数组,定义了两个对象:“Gambler” 和 “God”
      • 他们继承了人接口,其中Gambler实现了钱接口,God实现了加命接口;
      • 这个时候,当我们获取persion[i] 就可以 instanceof 两个接口
      • 即:Gambler  instanceof  Cash ;God instanceof Life  ;这样我们就可以 向上造型了,代码如下: 
//超类 Persion
public abstract class Persion {
    
}

 

//赚钱接口
public interface Cash {
    public abstract void addCash();
}
//加命接口
public abstract interface Life {
    public abstract void addLife();
}
//Gambler 继承人,实现赚钱钱接口
public class Gambler extends Persion implements Cash {
    int cash;
    @Override
    public void addCash() {
        cash+=100;
        System.out.println("得分:"+cash);

    }
}
//God 继承人,实现加命接口
public class God extends Persion implements Life{
    int life;
    @Override
    public void addLife() {
        this.life+=1;
        System.out.println("得命:"+life);
    }
}
public class Test {
    //测试
    public static void main(String[] args) {
        Test test = new Test();
        test.action();
    }
    
    //类型转换,同一个对象,被造型为不同得类型,有不同得实现功能
    public void action(){
        Persion[] persions= new Persion[2];
        persions[0] = new God();
        persions[1] = new Gambler();
        for(int i=0;i<persions.length;i++){
            if(persions[i] instanceof Life){
                Life life = (Life)persions[i];
                life.addLife();        //加命:1
            }
            if(persions[i] instanceof Cash){
                Cash cash = (Cash)persions[i];
                cash.addCash();        //赚钱:100
            }
        }
    }
}
  • 向上造型/自动类型转换
    • 超类型的引用指向派生类的对象
    • 能造型成为的数据类型:超类+所实现的接口
    • 能点出来什么,看引用的类型
    • 强制类型转换成功的条件
      • 引用所指向的对象,就是该类型
      • 引用所指向的对象,继承了该类或实现了该接口
      • instanceof 是 Java 的一个二元操作符,它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 类型的数据。
      • 强转时若不符合如上两个条件,则发生ClassCastException类型转换异常,建议在强转之前应先通过instanceof来判断引用指向的对象是否时该类型(强转若发生在循环里,有变量得,所以一定要判断)
public interface EnemyAward {
    public static final int FIRE = 0;
    public int LIFE = 1;

    public abstract int getAwardType();
}
public interface EnemyScore {
    int getScore();
}
//对象的多态:同一个对象被造型为不同的类型,有不同的功能
//强转,小转大,enemies[i] 对象 实现了该接口,父类型是FlyingObject
FlyingObject[] enemies = {};
....
for(int i=0;i<enemies.length;i++){
    FlyingObject f = enemies[i];
    if(f instanceof EnemyAward){
        EnemyAward award = (EnemyAward)f;
        int type = award.getAwardType();
     }
     if(f instanceof EnemyScore){
          EnemyScore s = (EnemyScore)f;
          score += s.getScore();
     }
}
  • 经典面试题,父类行的引用 赋值给 子类型的 变量上,需要强制类型转换  大转小
//已知如下代码,下列选项中哪个表达式会编译出错( )
interface IFace{}
class CFace implements IFace{}
class Base{}
public class ObRef extends Base{
  public static void main(String argv[]){ 
    ObRef ob = new ObRef();
    Base b = new Base(); 
    Object o1 = new Object(); 
    IFace o2 = new CFace();
  }
}


A.o1=o2;     
B.b=ob; 
C.ob=b;     //b 是 ob 的父类,将父类引用赋值给子类型变量上需要强制类型转换
D.o1=b; 
  • 关于抽象方法的一些说明
    • 抽象方法不可以是静态的
    • 不可以有方法体
    • 不可以在普通类中定义
    • 可以在接口中和抽象类中定义
  • 补充:java8 以后接口的新特性
    • java8以前,接口只能被类实现,类不能继承接口,遵循单继承多实现原则
    • java8以后,接口中可以包含静态方法和默认方法。
    • 默认方法的作用:
      • 格式:public default 返回值类型 方法名 (){}
      • 接口升级,可以避免改变其他实现类
    • 静态方法:照旧
      • 格式:publis static 返回值 方法名(){}
      • 接口中的静态方法和类中的静态方法一样,只能通过接口.静态方法名的方式调用
//定义接口
public interface EnemyAward {
    public static final int FIRE = 0;
    public int LIFE = 1;

    public default int getDefaultTest() {
        return 0;
    }
    public static BufferedImage addStaticTest(){
        return null;
    }
}
//类实现接口
public class FinalEx implements EnemyAward{
    public static void main(String[] args) {

        //new对象
        FinalEx a = new FinalEx();

        //通过对象去点默认方法
        a.getDefaultTest();

        //通过接口名.静态方法
        EnemyAward.addStaticTest();
    }
}
  • 注意: 
    • Java中,成员变量是没有重写的,成员变量不可以被继承或覆盖,即不能实现多态。
    • 只有方法才能构成多态。也就是说方法可以实现动态绑定,而变量用于是静态绑定。
    • 即:静态绑定就是变量本身什么类型,就用哪个里面的。
(单选题)下面的程序输出结果是( )。
public class A implements B {
	int k = 20;
	public static void main(String args[]) {
		int i;
		B c1 = new A();
		i = c1.k;
		System.out.println("i=" + i);
	}
}
interface B {
	int k = 10;
}


//输出10,因为C1事B类型,所以调用B里的

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值