4. 面向对象之单例模式与多态

3.2 多态

1. 简介

多态:多种形态
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2. 多态的实现

在这里插入图片描述

3.3 多态的实现

1. 案例

package com.imooc.dt;

/**
 * 动物类,父类
 */
public class Animal {
    //名称
    private String name;

    /**
     * 介绍
     */
    public void introduce() {
        System.out.println("我是动物.");
    }

    /**
     * 吃东西
     */
    public void eat() {

    }
}

package com.imooc.dt;

public class Cat extends Animal {
    //月份
    private String month;

    /**
     * 行为
     */
    public void sleep() {
        System.out.println("我喜欢睡懒觉");
    }

    @Override
    public void eat() {
        System.out.println("我喜欢吃小鱼干");
    }
}

package com.imooc.dt;

public class Dog extends Animal {
    //年龄
    private String age;
    public void walking() {
        System.out.println("我喜欢奔跑");
    }

    @Override
    public void eat() {
        System.out.println("我喜欢吃大骨头");
    }
}

2. 向上转型

在这里插入图片描述
在这里插入图片描述

3. 向下转型

动物转猫
在这里插入图片描述
猫转动物再转猫
在这里插入图片描述
猫转狗
在这里插入图片描述

第10行对比

4. instanceof类比较

在这里插入图片描述
在这里插入图片描述

3.4 抽象类

1. 简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以,abstract描述的类
抽象类不允许实例化,可以向上转型指向子类实例
在这里插入图片描述
在这里插入图片描述

2. 抽象类的抽象方法

1.抽象类中某方法由abstract修饰,则该方法就为抽象方法
2.抽象方法没有方法体,并且其子类必须重写该方法,如果子类不重写,则子类要设置为抽象类
3.有抽象方法的类一定是抽象类
4.抽象方法体现了抽象类存在的意义

package com.imooc.lei;

import com.sun.scenario.effect.impl.prism.PrTexture;

/**
 * 抽象类
 */
public abstract class Person {
    private String name;
    private int age;

    public void pao() {
        System.out.println("我是非抽象方法");
    }

    /**
     * 抽象方法
     */
    public abstract void beat();

}

3. 总结

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
向上转型:就是父类转子类
在这里插入图片描述

4.1 接口

1. 背景

在这里插入图片描述
在这里插入图片描述

2. 案例:基于继承

父类:电话,功能打电话

package com.imooc.ex;

/**
 * 电话
 */
public class Telphone {
    //品牌
    private String brand;
    //价格
    private int price;

    public String getBrand() {
        return brand;
    }

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

    public int getPrice() {
        return price;
    }

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

    //功能
    public void call() {
        System.out.println("可以打电话");
    }
}

二代手机

package com.imooc.ex;

/**
 * 二代手机,继承电话所有功能,还可以发短信
 */
public class SecondPhone extends Telphone {
    public void message() {
        System.out.println("可以发短信");
    }
}

三代手机

package com.imooc.ex;

/**
 * 三代手机:继承二代手机,功能还可以看视频,听音乐
 */
public class ThirdPhone extends SecondPhone {
    public void vedio() {
        System.out.println("可以看视频");
    }

    public void music() {
        System.out.println("可以听音乐");
    }
}

实现一个3代手机

package com.imooc.ex.alc;

import com.imooc.ex.ThirdPhone;

public class app {
    public static void main(String[] args) {
        //实现一个3代手机
        ThirdPhone thirdPhone = new ThirdPhone();
        //一代功能
        thirdPhone.call();
        //二代功能
        thirdPhone.message();
        //三代自己的功能
        thirdPhone.vedio();
        thirdPhone.music();
    }
}

在这里插入图片描述

3. 基于2的问题

在这里插入图片描述
继承 – 适用于有一定的演变的对象。一代一代的迭代

当遇到对于跨度比较大的不同的对象,存在某些共同点,比如照相机和电话都可以拍照,又比如电脑、手机、电话手表都可以微信电话。
那如何提取他们的共同点?— 接口interface

4. 案例:基于接口

idea快捷键:实现接口方法 ctrl+i

拍照接口

package com.imooc.im;

/**
 * IPhoto接口:拍照模版,不具体如何拍照,即没有方法体
 */
public interface IPhoto {
    //拍照模版,不具体如何拍照,即没有方法体
    public void photo();
}

相机类:实现拍照功能

package com.imooc.im;

/**
 * 相机类
 */
public class Camera implements IPhoto {
    //实现IPhoto的photo,需要具体实现
    @Override
    public void photo() {
        System.out.println("相机拍照");
    }
}

手机类实现拍照功能

package com.imooc.im;

import com.imooc.ex.ThirdPhone;

/**
 * 手机类
 */
public class Phone extends ThirdPhone implements IPhoto {

    /**
     * 实现方法:拍照
     */
    @Override
    public void photo() {
        System.out.println("手机拍照");
    }
}

测试

package com.imooc.im.app;

import com.imooc.im.Camera;
import com.imooc.im.IPhoto;
import com.imooc.im.Phone;

public class MainApp {
    public static void main(String[] args) {
        //创建相机
        IPhoto camera = new Camera();
        camera.photo();
        //创建手机1:基于 IPhoto 接收,只能调用Phone实现的方法
        IPhoto iPhoto = new Phone();
        iPhoto.photo();
        //创建手机2:基于 Phone 接收,才能调用其他非实现方法
        Phone phone = new Phone();
        phone.photo();
        phone.message();
    }

}

在这里插入图片描述

5. default关键字使用

接口中某些方法不强制实现类重写该方法,可以将方法由default关键字修饰

package com.imooc.im;

/**
 * IPhoto接口:拍照模版,不具体如何拍照,即没有方法体
 */
public interface IPhoto {
    /**
     * default:在接口中修饰方法.该方法为默认方法且可以有方法体,实现类可不重写(即:可写,可不写)
     */
    default void connection() {
        System.out.println("接口中的默认方法");
    }
    
    /**
     * 拍照模版
     */
    public void photo();
}

Camera类实现IPhoto ,未重写connection默认方法
在这里插入图片描述
Phone类实现IPhoto ,重写connection默认方法
在这里插入图片描述
测试
在这里插入图片描述

6. static关键字使用

接口中的静态方法:该方法不能被实现类重写
在这里插入图片描述

测试
在这里插入图片描述
无法通过实现类调用

7. default和static区别

调用时: default方法可以对象去调用,static只能接口名去调用

实现类: default修饰的方法可以被重写,而static不可以。值得注意的是,default重写要调用接口方法需要接口名.super实现

8. 实现多接口:方法重复

对于实现类同时实现接口A接口B…时,他们存在同一个方法名时,实现类需要重写该方法,就算该方法是默认方法也需要重写

接口1

package com.imooc.im;

/**
 * IPhoto接口:拍照模版,不具体如何拍照,即没有方法体
 */
public interface IPhoto {
    /**
     * default:在接口中修饰方法.该方法为默认方法且可以有方法体,实现类可不重写(即:可写,可不写)
     */
    default void connection() {
        System.out.println("IPhoto接口中的默认方法");
    }

    /**
     * 拍照模版
     */
    public void photo();
}

接口2

package com.imooc.im;

/**
 * IPhoto接口:拍照模版,不具体如何拍照,即没有方法体
 */
public interface IPhoto1 {
    /**
     * default:在接口中修饰方法.该方法为默认方法且可以有方法体,实现类可不重写(即:可写,可不写)
     */
    default void connection() {
        System.out.println("IPhoto1接口中的默认方法");
    }

    /**
     * 拍照模版
     */
    public void photo1();
}

实现类:多接口实现

package com.imooc.im.impl;

import com.imooc.im.IPhoto;
import com.imooc.im.IPhoto1;

/**
 * 相机类
 */
public class Camera implements IPhoto, IPhoto1 {
    /**
     * default:在接口中修饰方法.该方法为默认方法且可以有方法体,实现类可不重写(即:可写,可不写)
     * 在多接口实现类中,多接口中默认方法存在名称一致时,需要重写
     */
    @Override
    public void connection() {
        IPhoto.super.connection();
        IPhoto1.super.connection();
        System.out.println("默认方法需要重写!!!");
    }

    /**
     * 实现IPhoto的photo,需要具体实现
     */
    @Override
    public void photo() {
        System.out.println("相机拍照");
    }

    /**
     * 实现IPhoto1的photo1,需要具体实现
     */
    @Override
    public void photo1() {
        System.out.println("单反相机拍照");
    }


}

测试
在这里插入图片描述

9. 接口与继承存在同名方法

父类
在这里插入图片描述
接口
在这里插入图片描述
实现类且子类:未重写同名方法connection
在这里插入图片描述
测试
在这里插入图片描述
结论:虽然未被重写,底层是子类继承connection方法,隐式重写实现类的默认connection方法
在这里插入图片描述
可以看到此时的connection无法被重写

10. 接口继承

在这里插入图片描述

4.2 内部类

1. 简介

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2. 内部类分类

在这里插入图片描述

3. 成员内部类

3.1 定义内部类

内部类中最常见的就是成员内部类也称为普通内部类

package com.imooc.lei;

/**
 * 外部类Person
 */
public class Person {

    private int age;

    /**
     * 提供内部类获取
     *
     * @return
     */
    public Heart getHeart() {
        return new Heart();
    }

    public Work getWork() {
        return new Work();
    }

    /**
     * 成员内部类:隐藏在外部类里面,无法被其他类直接获取
     */
    public class Heart {
        public String beat() {
            return "我是Person的内部类Heart";
        }
    }

    /**
     * 访问修饰符:成员内部类的访问修饰符可以任意,但是访问范围会受到影响
     */
    private class Work {
        public String beat() {
            return "我是Person的内部类work";
        }
    }

}

3.2 调用内部类

内部类在外部使用时,无法直接实例化,需要借由外部类信息才能完成实例化

package com.imooc.lei.app;

import com.imooc.lei.Person;

public class MainApp {
    /**
     * 演示:调用内部类
     *
     * @param args
     */
    public static void main(String[] args) {
        //方式1:new 外部类.new 内部类
        Person.Heart heatr = new Person().new Heart();
        System.out.println("方式1: new 外部类.new 内部类:" + heatr.beat());
        //方式2: 外部类对象.new 内部类
        Person person = new Person();
        Person.Heart heart1 = person.new Heart();
        System.out.println("方式2: 外部类对象.new 内部类:" + heart1.beat());
        //方式3: 外部类对象.获取方法	(推荐)
        Person.Heart heart3 = person.getHeart();
        System.out.println("方式3: 外部类对象.获取方法:" + heart3.beat());
        //方式4:内部类未被public修饰时
//        Person.Work work = new Person().new Work();//无法获取Work类
//        System.out.println("方式3: 外部类对象.获取方法:"+person.getWork().beat());//无法获取Work类的beat方法
    }
}

在这里插入图片描述

3.3 内部类使用外部类成员

内部类可以直接访问外部类的成员;如果出现同名属性,优先访问内部类中定义的
可以通过外部类.this.成员的方式,访问外部类的同名信息

package com.imooc.lei;

/**
 * 外部类Person
 */
public class Person {
    //名称
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * 提供内部类获取
     *
     * @return
     */
    public Heart getHeart() {
        return new Heart();
    }

    /**
     * 成员内部类:隐藏在外部类里面,无法被其他类直接获取
     */
    public class Heart {
        //名称
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        /**
         * 内部类获取外部类name属性
         * 获取方式:外部类.this.成员
         * @return
         */
        public String getExternalName() {
            return Person.this.name;
        }
        
    }
    
}

在这里插入图片描述

4. 静态内部类

4.1 定义静态内部类

package com.imooc.lei;

/**
 * 外部类Person
 */
public class Person {
    //名称
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    /**
     * 提供内部类获取
     *
     * @return
     */
    public Heart getHeart() {
        return new Heart();
    }

    /**
     * Heart静态内部类:隐藏在外部类里面,无法被其他类直接获取
     */
    public static class Heart {
        //名称
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

    }
}

在这里插入图片描述

4.2 静态内部类调用外部类成员

在这里插入图片描述
测试
在这里插入图片描述

package com.imooc.lei;

import com.sun.scenario.effect.impl.prism.PrTexture;

/**
 * 外部类Person
 */
public class Person {
    //名称
    private String name;
    private static int age = 18;

    public Person() {
    }

    public Person(String name) {
        this.name = name;
    }

    public void sMethod() {
        System.out.println("我是外部类的非静态成员方法");
    }

    public static void fMethod() {
        System.out.println("我是外部类的静态成员方法");
    }

    /**
     * 提供内部类获取
     *
     * @return
     */
    public Heart getHeart() {
        return new Heart();
    }

    /**
     * Heart静态内部类:隐藏在外部类里面,无法被其他类直接获取
     */
    public static class Heart {
        //名称
        private String name;

        /**
         * 内部类调用外部类非静态成员,需要通过实例化外部类获取
         * 静态成员可直接获取
         *
         * @param person
         */
        public void setNameByWeb(Person person) {
            //this.name = Person.this.name;//错误演示,无法调用外部类非静态成员
//            Person person=new Person();
            //获取非静态成员
            System.out.println("名称:" + person.name);
            person.sMethod();
            //获取静态成员
            Person.fMethod();
            System.out.println("年龄:" + Person.age);
        }

        public String beat() {
            return "我是静态内部类;";
        }
    }
}

4.3 调用静态内部类的静态成员

获取静态内部类静态方法:外部类.内部类.静态方法
在这里插入图片描述

在这里插入图片描述

5. 方法内部类

在这里插入图片描述

package com.imooc.lei;

import com.sun.scenario.effect.impl.prism.PrTexture;

/**
 * 外部类Person
 */
public class Person {

    /**
     * 方法内部类方法,返回值为Object
     * 方法内部类中不可以有静态成员
     *
     * @return new 方法内部类方法,缺点,获取到的信息不多
     */
    public Object getHeart() {
        /**
         * 方法内部类
         */
        class Heart {
            //名称
            private String name = "我是方法内部类的属性";

            public String getName() {
                return name;
            }

            public String beat() {
                return "我是方法内部类的成员方法;";
            }
        }
        return new Heart().beat();
    }
}

在这里插入图片描述

6. 匿名内部类

适用于,该类项目只使用一次实例,并且内容较小
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.imooc.lei;

import com.sun.scenario.effect.impl.prism.PrTexture;

/**
 * 外部类Person
 */
public abstract class Person {
    private String name;
    private int age;

    public abstract void beat();

}

在这里插入图片描述
在这里插入图片描述

*****************************************************************************************************************

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

与海boy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值