10.接口、多态

接口

生活中的接口:规范、规则

Java中的接口:规范、规则,如果要实现接口,必须要实现接口中的抽象方法。解决了类的单继承的局限性。

概念:

接口就是一种规范和约定,将来实现接口的实现类,必须遵守接口的规则去重写接口中的抽象方法。

接口还解决了Java中类只能单继承的局限性。

创建方式:

接口使用interface关键字,就是把类中的class换成interface

interface 接口名{}

实现接口:

实现接口用implements关键字

class 类 implements 接口名{

}

类实现接口后,要么这个类是抽象类,要么重写接口中的所有抽象方法

接口的特点:

1.接口的成员变量只能是常量,声明的时候,必须要赋值,不能改变

默认以 public static final 修饰

2.接口没有构造方法,所以接口不能实例化

3.接口中的普通方法,只能是抽象方法,默认以 public abstract修饰

package com.day10.interface1;

public interface Father {

    //接口中默认的成员变量是常量
    //默认以 public static final 修饰
    String name="jack";

    //接口中,不存在构造方法,所以不能创建对象
//    public Father(){
//
//    }

    //接口中的普通方法只能是抽象方法
    //起到一个约束性的作用
    public abstract void code();

    //接口中可以写静态方法,这个静态方法,必须要有具体的实现
    public static void hello(){
        System.out.println("接口中的静态方法");
    }

    //接口中还可以定义默认的default方法
    default void show(){
        System.out.println("接口中的默认方法");
    }

}



package com.day10.interface1;

public interface Mather {

    //Interface abstract methods cannot have body即不能有代码体
    //接口中的普通方法,默认都是抽象方法
    //不加public  abstract也可以
    void sing();
    
}



package com.day10.interface1;
//接口的实现类,
//要么是抽象类,
//要么重写所有父接口中的抽象方法
public class Son implements Father,Mather{

    @Override
    public void code() {
        System.out.println("子类重写Father接口中的方法");
    }

    @Override
    public void sing() {
        System.out.println("子类重写Mather接口中的方法");
    }
}



package com.day10.interface1;

public class Test {
    public static void main(String[] args) {
        //接口中的成员变量是静态常量,可以通过接口名直接调用
        System.out.println(Father.name);
        //接口中的成员变量是常量,不能重新赋值
        //Father.name="Tom";

        //接口中的静态方法可以通过名称直接调用
        Father.hello();

        //接口中的默认方法不能直接调用
        //Father.show();

        Son son = new Son();
        //子实现类可以继承父接口中的default方法
        son.show();

        son.code();
    }
}

接口中的静态方法、default方法

jdk8中,为了增加接口的可扩展性,对接口新增了static方法和default方法,可以增加接口的灵活性。

static方法,可以通过接口名调用。

default方法不能通过接口名调用,但是可以被实现类继承。

在jdk9中,可以声明private方法,为了提高接口中,内部代码的可重用性。

private可以在内部被调用,但是会将实现的细节对外隐藏。

面试题:接口和抽象类的相同点和不同点?

相同点:1.接口和抽象类都不能被实例化,主要用于被其他类实现和继承。

2.接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的普通子类都必须实现这些抽象方法。

不同点:

声明上:

抽象类:通过abstract关键字修饰

接口:interface 接口名{}

子类:

抽象类:子类使用extends关键字来继承抽象类,如果子类不是抽象类,则需要提供抽象类中所有声明的方法的实现。

接口:子类使用implements关键字来实现接口,需要提供接口中所有声明的方法的实现。

成员变量:

抽象类:既可以定义普通成员变量,也可以定义静态常量

接口:只能定义静态常量,不能定义普通成员变量

构造方法:

抽象类:可以有构造方法,构造方法不用来实例化,一般用来给子类访问

接口:没有构造方法,所以接口不能实例化

普通方法:

抽象类:可以有抽象方法,也可以有普通方法、静态方法

普通方法和静态方法的使用,可以和普通类的用法一样。

接口:只能包含抽象方法、静态方法、默认方法和私有方法,不能为普通方法提供方法实现

多态

概念

一个对象在不同时刻,体现出来的不同状态

Java中写法

父类引用指向子类的对象

格式:声明对象的时候

父类名 变量名 = new 子类名();

或者

父接口 变量名 = new 实现类名();

多态的前提

1.要求有继承或者接口的实现

2.要有方法重写

3.有父类/父接口的引用指向子类对象

成员访问特点

1.成员变量:编译看左边,运行看左边

2.成员方法:编译看左边,运行看右边

多态的好处

可以提升代码的维护性和扩展性

多态的弊端

父类不能使用子类特有的功能。

子类可以当作父类使用,父类不能当作子类使用

在Java的多态中,可以通过转型完成子类特有方法的调用

转型分为:

向上转型:向上转型就是多态,子类对象当作父类使用

写法:父类名 变量名 = new 子类名();

含义:右侧的子类对象,被当作父类看待、使用

比如:

Animal animal = new Dog();

创建一个Dog对象,当作Animal类看待、使用

向上转型一定是安全的,类似于基本类型的隐式转换

向下转型:子类被向上转型为父类后,想调用子类特有的功能, 需要将被当作父类的子类对象,还原成子类

写法:子类 变量 = (子类)向上转型的父类;

比如:

Animal animal = new Dog(); 先向上转型

Dog dog = (Dog)animal; 再向下转型

子类对象Dog被当作父类Animal使用,又将animal还原成Dog对象。

还原之后的dog对象,可以调用子类的特有功能。

向下转型的对象,必须是原对象本身,如果是别的对象,无法还原成自己的对象, 类似于,一个Cat对象,可以被当作Animal对象,但是不能被还原成一个Dog对象

多态的分类

编译时多态:靠方法重载体现。

方法重载具有不同的参数,当我们调用重载的方法的时候,会根据传入参数的不同,自动调用对应具体参数的方法。

运行时多态:靠方法重写体现。

运行时多态,在创建对象之后,调用方法的时候,才去确定调用的是哪个方法, 通过动态绑定来实现的。

package com.day10.duotai;

public class Father {
    public String name="jack";
    public int age=20;

    public void show(){
        System.out.println("父类的show方法");
    }
    public void say(){
        System.out.println("父类的say方法");
    }
}



package com.day10.duotai;

public class Son extends Father implements Mother{
    public String name="tom";
    public String gender="男";

    @Override
    public void show(){
        System.out.println("子类重写父类的show方法");
    }

    public void hello(){
        System.out.println("这是子类的hello方法");
    }


    @Override
    public void sing() {
        System.out.println("重写的Mother接口中的sing方法");
    }
}


package com.day10.duotai;

public interface Mother {
    void sing();

    public static void show(){
        System.out.println("这是父接口中的静态方法");
    }
    default void show1(){
        System.out.println("父接口中的默认方法");
    }
}



package com.day10.duotai;

public class Test {
    public static void main(String[] args) {
        //多态创建Father对象
        Father f = new Son();
        //多态调用
        //调用属性,编译看左边,运行看左边
        System.out.println(f.name);
        System.out.println(f.age);
       // System.out.println(f.gender);

        //调用方法,体现了多态性,编译看左边,运行看右边
        f.show();
        f.say();
        //f.hello();

        //将被当作父类使用的子类对象,还原成子类对象
        //调用子类特有的方法
        Son son=(Son) f;
        son.hello();

        System.out.println(son==f);//true

        //创建接口多态
        Mother m = new Son();
        //多态调用子类的sing方法
        m.sing();

        //接口中的静态方法,不能通过多态创建的对象调用
        //只能通过接口名访问
        // m.show();

        //多态创建的接口对象,可以调用接口中的default方法
        m.show1();
    }
}
  • 35
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值