抽象类和接口

目录

1. 抽象类

2. 抽象类实现多态

3. final关键字

3.1 final 修饰属性

3.2 final修饰方法

3.3 final修饰类

4. 接口

4. 抽象类和接口的区别


1. 抽象类

1.抽象方法没有方法体吗,必须存在于抽象类中 均使用 abstract 修饰

2.抽象类不能直接 new 对象,必须通过 new 子类的方式创建对象(即多态向上转型)

3.子类必须重写抽象类中的所有抽象方法,除非子类也是抽象对象

4.抽象类中可以写普通属性、静态属性,普通方法、静态方法,构造方法

5.抽象类实现多态的方式与之前一致

public abstract class Animal {//抽象类
    private String animalType;

    public String getAnimalType() {
        return animalType;
    }
    public void setAnimalType(String animalType) {
        this.animalType = animalType;
    }
    public Animal(String animalType){
        this.animalType = animalType;
    }
    public Animal(){}

    static int num ;

    public abstract void eat();//抽象方法

    public static void main(String[] args) {、

    }
}
public class Tiger extends Animal{
    @Override
    public void eat() {
        System.out.println("老虎吃人");
    }
}
public abstract class Pet extends  Animal{
    public abstract void playWithMaster();
}
public class Dog extends Pet{
    @Override
    public void eat() {//重写间接父类的抽象方法
        System.out.println("狗吃骨头");
    }

    @Override
    public void playWithMaster() {//重写直接父类的抽象方法
        System.out.println("狗狗陪主人玩飞盘");
    }
}
public class TestAnimal {
    public static void main(String[] args) {
//        Animal animal = new Animal();

        Animal tiger = new Tiger();

        tiger.eat();

        System.out.println("--------------------------------------");

        Dog dog = new Dog();
        dog.eat();
        dog.playWithMaster();

        System.out.println("--------------------------------------");

        Animal dog1 = new Dog();//间接父类
        dog1.eat();

        Pet dog2 = new Dog();
        dog2.eat();
        dog2.playWithMaster();
    }
}

2. 抽象类实现多态

5.抽象类实现多态的方式与之前一致

 向上转型三种方式

1.父类作为形参  子类作为实参

2. 声明父类类型的返回值 实际返回值为子类类型

3.父类类型的数组/集合 实际元素为子类类型

public abstract class Door {
    private String brand;
    private double price;

    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }
    public Door() {
    }
    public Door(String brand, double price) {
        this.brand = brand;
        this.price = price;
    }
    public abstract void open();

    public abstract void close();
}
public class CommonDoor extends Door{
    private String key;

    public String getKey() {
        return key;
    }
    public void setKey(String key) {
        this.key = key;
    }
    public CommonDoor() {
    }
    public CommonDoor(String brand, double price, String key) {
        super(brand, price);
        this.key = key;
    }
    @Override
    public void open() {
        System.out.println("普通门插入钥匙,zhiya一声 门开了");
    }

    @Override
    public void close() {
        System.out.println("普通门关门,duang的一声,关门");
    }
}
public class SecurityDoor extends Door{
    private String password;

    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
    public SecurityDoor() {

    }
    public SecurityDoor(String brand, double price, String password) {
        super(brand, price);
        this.password = password;
    }

    @Override
    public void open() {
        System.out.println("防盗门开门,输入密码,门开了");
    }

    @Override
    public void close() {
        System.out.println("防盗门关门,自动关门");
    }
}
public class Person {
    public void openCommonDoor(CommonDoor cd){
        cd.open();
    }
    public void closeCommonDoor(CommonDoor cd){
        cd.close();
    }
    public void openSecurityDoor(SecurityDoor securityDoor){
        securityDoor.open();
    }
    public void closeSecurityDoor(SecurityDoor securityDoor){
        securityDoor.close();
    }

    // --------------------------------------------------------------------

    public void openDoor(Door door){
        door.open();
    }
    public void closeDoor(Door door){
        door.close();
    }

    // --------------------------------------------------------------------

    public Door buyDoor(double money){
        if(money > 500){
            return new SecurityDoor();
        }else{
            return new CommonDoor();
        }
    }
}
public class TestDoor {
    public static void main(String[] args) {
        Person zs = new Person();

        CommonDoor commonDoor = new CommonDoor("小金刚", 500, "原配钥匙");

        SecurityDoor securityDoor = new SecurityDoor("大金刚", 1000, "admin666");

        zs.openDoor(commonDoor);
        zs.openDoor(securityDoor);

        System.out.println("------------------------------------------");

        Door door = zs.buyDoor(333);

        zs.openDoor(door);

        System.out.println("------------------------------------------");

        Door [] doors = new Door[2];

        doors[0] = new CommonDoor();
        doors[1] = new SecurityDoor();
    }
}

3. final关键字

final 关键字可以用于修饰属性、方法、类

final关键字与我们之前所学习的访问修饰符无关

3.1 final 修饰属性

被 final 修饰的属性称为常量,常量名称要求全部大写,多个单词之间用 _ 分割

通常(99%)在定义的时候赋值,或者在构造方法中赋值

以上两种方式都是为了保证在使用常量之前是有值的

基本数据类型:被final修饰的基本数据类型,一旦定义就不能再改变

引用数据类型:被final修饰的引用数据类型,定义之后地址不能再改变 ,值可以改变

public class TestFinalField {
    final double PI = 3.14;
    double radius;

    final  String COUNTRY_NAME;

    final char [] SIGN = new char[3];

    final Dog DOG = new Dog();

    public TestFinalField() {
        COUNTRY_NAME = "中华人民共和国";
    }

    public TestFinalField(double radius) {
        this.radius = radius;
        COUNTRY_NAME = "中华人民共和国";
    }

    public static void main(String[] args) {
        TestFinalField testFinalField = new TestFinalField();
        testFinalField.radius = 10;
//        testFinalField.pi = 3.24;
//        testFinalField.COUNTRY_NAME = "中国";

        testFinalField.SIGN[0] = 'A';
        testFinalField.SIGN[1] = 'B';
        testFinalField.SIGN[2] = 'C';

        testFinalField.DOG.strain = "金毛";

        System.out.println(testFinalField.radius * testFinalField.radius * testFinalField.PI );

        TestFinalField testFinalField1 = new TestFinalField();
    }
}

再实际开发中,被final修饰的属性表示常量,没必要存在多份,可以在加上static修饰

static final 修饰的内容:静态  常量

 被static修饰的常量通常在定义的时候赋值  或者在静态代码块中赋值

以上两种方式都是为了保证在使用常量之前都是有值的

public class TestFinalStaticField {
    public static final double PI = 3.14;

    static final String COUNTRY_NAME;

    static{
        COUNTRY_NAME = "中国";
    }

    public TestFinalStaticField() {
    }
}

3.2 final修饰方法

被 final 修饰的方法表示(可以被继承)不能被子类重写

public class TestFinalMethod {

}

class A{
    public void m1(){
        System.out.println("A 类m1方法");
    }

    public final void m2(){
        System.out.println("A 类m2方法");
    }
}
class B extends A{
    public void m1(){
        System.out.println("B 类重写m1方法");
    }
    public static void main(String[] args) {
        B b = new B();
        b.m1();
        b.m2();
    }
}

3.3 final修饰类

被 final 修饰的类不能被其他类继承

public class TestFinalClass {
    public static void main(String[] args) {

    }
}

final class C extends B{

}

4. 接口

接口使用关键字interface修饰

interface:界面

UI:User Interface 用户交互界面

接口是一种约定、一种规范 接口只关注约定本身  不关注具体实现

接口是一种能力  谁实现了这个接口,谁就拥有了某项能力

1.接口中的方法默认为全局抽象方法  不管是否书写均使用 public abstract 修饰

2.接口不能直接 new 对象 必须通过 new 实现类(子类)的方式创建对象(多态向上转型)

3.实现类(子类)必须实现(重写)接口中所有的抽象方法,除非实现类也是抽象类 或者 接口

4.接口中不能书写普通属性 普通方法(JDK7-) 静态方法(JDK7-) 构造方法

5.接口可以继承多个接口 一个类也可以实现多个接口 多个接口之间使用逗号分割

6.接口实现多态的方式与之前一致

面试题:Java支持多继承吗?

不支持 但是可以使用接口继承多个接口的方式 实现类似多继承的效果

public interface USB {

    public static final int NUM = 10;

   void connect();

   public default void m1(){

   }
    public static void main(String[] args) {

    }
}
public class Mouse implements USB{
    @Override
    public void connect() {
        System.out.println("鼠标链接上USB接口  可以点击世界了");
    }
}
public abstract class Converter implements  USB{
    /**
     *  转换方法
     */
    public abstract  void convert();
}
public class HuaWeiConverter extends Converter{
    @Override
    public void convert() {
        System.out.println("将网络进行转换");
    }

    @Override
    public void connect() {
        System.out.println("连接USB接口实现网络传输");
    }
}
public class TestUSB {
    public static void main(String[] args) {
//        USB usb = new USB();

        USB mouse = new Mouse();

        mouse.connect();

        System.out.println("--------------------------------");

        USB converter1 = new HuaWeiConverter();

        converter1.connect();

        HuaWeiConverter huaWeiConverter = new HuaWeiConverter();

        huaWeiConverter.convert();
        huaWeiConverter.connect();
    }
}

手机案例

public abstract class Phone {
    private String brand;
    private String type;
    private double price;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    public abstract void call();

    public abstract void sendMessage(String message);
}
public class CommonPhone extends Phone implements Audio,NetWork,Game{
    private String keyboardType; // 键盘类型  比如 九键 二十六键

    public String getKeyboardType() {
        return keyboardType;
    }

    public void setKeyboardType(String keyboardType) {
        this.keyboardType = keyboardType;
    }

    @Override
    public void call() {
        System.out.println("普通手机打电话,按键拨号,体验一般");
    }

    @Override
    public void sendMessage(String message) {
        System.out.println("普通手机发短信,按键打字,体验一般:" + message);
    }

    @Override
    public void playAudio(String audioName) {
        System.out.println("普通手机播放音乐,音质感人:" + audioName);
    }

    @Override
    public void playGame(String gameName) {
        System.out.println("普通手机打游戏,很经典:" + gameName);
    }

    @Override
    public void connect() {
        System.out.println("普通手机连接2G网络  体验非一般");
    }
}
public class SmartPhone extends Phone implements Video, Audio,Game,Photo, NetWork {
    private double screenSize; // 屏幕尺寸

    public double getScreenSize() {
        return screenSize;
    }

    public void setScreenSize(double screenSize) {
        this.screenSize = screenSize;
    }

    @Override
    public void call() {
        System.out.println("智能手机打电话,语音拨号,体验很棒");
    }

    @Override
    public void sendMessage(String message) {
        System.out.println("智能手机发短信,语音输入,体验很棒");
    }

    @Override
    public void playAudio(String audioName) {
        System.out.println("智能手机播放音乐,音质很棒:" + audioName);
    }

    @Override
    public void playGame(String gameName) {
        System.out.println("智能手机打游戏,很丝滑:" + gameName);
    }

    @Override
    public void connect() {
        System.out.println("智能手机连接5G网络 飞一般的感觉");
    }

    @Override
    public void takePhoto() {
        System.out.println("咔嚓一下 记录美好 记录你我");
    }

    @Override
    public void playVideo(String videoName) {
        System.out.println("智能手机播放视频,高清画质,很流畅:" + videoName);
    }
}
public class SmartPhone extends Phone implements Video, Audio,Game,Photo, NetWork {
    private double screenSize; // 屏幕尺寸

    public double getScreenSize() {
        return screenSize;
    }

    public void setScreenSize(double screenSize) {
        this.screenSize = screenSize;
    }

    @Override
    public void call() {
        System.out.println("智能手机打电话,语音拨号,体验很棒");
    }

    @Override
    public void sendMessage(String message) {
        System.out.println("智能手机发短信,语音输入,体验很棒");
    }

    @Override
    public void playAudio(String audioName) {
        System.out.println("智能手机播放音乐,音质很棒:" + audioName);
    }

    @Override
    public void playGame(String gameName) {
        System.out.println("智能手机打游戏,很丝滑:" + gameName);
    }

    @Override
    public void connect() {
        System.out.println("智能手机连接5G网络 飞一般的感觉");
    }

    @Override
    public void takePhoto() {
        System.out.println("咔嚓一下 记录美好 记录你我");
    }

    @Override
    public void playVideo(String videoName) {
        System.out.println("智能手机播放视频,高清画质,很流畅:" + videoName);
    }
}
package com.atguigu.test6;

/**
 *  音频接口
 */
public interface Audio {
    void playAudio(String audioName);
}

package com.atguigu.test6;

/**
 *  游戏接口
 */
public interface Game {
    void playGame(String gameName);
}

package com.atguigu.test6;

/**
 *  联网接口
 */
public interface NetWork {
    void connect();
}

package com.atguigu.test6;

/**
 *  拍照接口
 */
public interface Photo {
    void takePhoto();
}

package com.atguigu.test6;

/**
 *  视频接口
 */
public interface Video {
    void playVideo(String videoName);
}


package com.atguigu.test6;

/**
 * @author WHD
 * @description TODO
 * @date 2023/4/14 16:33
 */
public class TestPhone {
    public static void main(String[] args) {
        CommonPhone nokia = new CommonPhone();
        nokia.setBrand("诺基亚");
        nokia.setPrice(850);
        nokia.setType("N95");
        nokia.setKeyboardType("九键");


        nokia.connect();
        nokia.sendMessage("睡了吗?");
        nokia.call();
        nokia.playAudio("《想你的夜》");
        nokia.playGame("《贪吃蛇》");


        System.out.println("----------------------------------------------------------");

        SmartPhone huawei = new SmartPhone();
        huawei.setBrand("华为");
        huawei.setPrice(5500);
        huawei.setType("Mate 50 PRO MAX PLUS");
        huawei.setScreenSize(15);

        huawei.connect();
        huawei.sendMessage("真的睡了吗?");
        huawei.call();
        huawei.playAudio("《我的滑板鞋-庞老师》");
        huawei.playVideo("《战狼》");
        huawei.takePhoto();
        huawei.playGame("《王者荣耀》");



    }
}

打印机案例

组成部分-属性:墨盒  纸张

墨盒本身就是一种规范,所以我们可以使用接口描述

纸张本身也是一种规范,也可以用接口来描述

功能-方法:打印

public class Printer {
    private InkBox inkBox;//墨盒
    private Paper paper;//纸张

    public void setInkBox(InkBox inkBox){
        this.inkBox = inkBox;
    }
    public InkBox getInkBox(){
        return inkBox;
    }

    public void setPaper(Paper paper){
        this.paper = paper;
    }
    public Paper getPaper(){
        return paper;
    }

    public void print(){  //打印功能
        System.out.println("使用"+ this.getInkBox().getInkBoxType() + "在"+ this.getPaper().getPaperType() +"纸张上打印");
    }
}
package com.atguigu.test1;

/**
 *  墨盒接口
 */
public interface InkBox {  //墨盒接口
    String getInkBoxType();
}
public class BlackInkBox implements  InkBox{ //实现墨盒
    @Override
    public String getInkBoxType() {
        return "黑色墨盒";
    }
}
public class ColorInkBox implements  InkBox{  //实现墨盒
    @Override
    public String getInkBoxType() {
        return "彩色墨盒";
    }
}
public interface Paper {  //纸张接口
    String getPaperType();
}
public class A4 implements  Paper{  //实现纸张接口
    @Override
    public String getPaperType() {
        return "A4";
    }
}
public class B5 implements  Paper{  //实现接口
    @Override
    public String getPaperType() {
        return "B5";
    }
}
public class TestPrinter {
    public static void main(String[] args) {
        Printer hp = new Printer();//实例打印机对象

        Paper a4 = new A4();//实例纸张对象
        Paper b5 = new B5();//实例对象

        hp.setPaper(a4);

        InkBox black = new BlackInkBox();//实例墨盒对象
        InkBox color = new ColorInkBox();

        hp.setInkBox(black);

        hp.print();

        System.out.println("-------------------------------------------------");

        InkBox [] inkBoxes = new InkBox[3];//数组类

        inkBoxes[0] = new BlackInkBox();
        inkBoxes[1] = new ColorInkBox();
    }
}

4. 抽象类和接口的区别

相同点

        代表系统的抽象层

        都不能被实例化

        都能包含抽象方法

        用于描述系统提供的服务,不必提供具体实现

不同点

        在抽象类中可以为部分方法提供默认实现(属性等),而接口中只能包含抽象方法

        抽象类便于复用,接口便于代码维护

        一个类只能有一个直接父类,但可以实现多个接口 

使用原则

        接口做系统与外界交互的窗口

        接口提供服务

        接口本身一旦制定,就不允许随意修改

        抽象类可以实现部分功能,还有部分功能可作为系统的扩展点

面向对象的设计原则

        多组合,少继承

        针对接口编程

        针对扩展开放,针对改变关闭

当关注事物的本质,使用抽象类        因为抽象类可以写普通属性来描述事物

当关注某个功能,使用接口        接口不能写普通属性来描述事物  只能描述抽象行为

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值