5.抽象和接口,static,内部类

1.回顾-泛化

泛化:父类的引用指向子类的对象
泛化的好处:统一管理,实现多态
泛化的缺点:丢失具体信息

再一次确认往下转型是不安全的
如何安全:先判断类型xx instanceof 类

1.1、instanceof

使用instanceof时,对象的类型必须和instanceof后面的参数所指定的类在继承上有上下级关系
使用:xx instanceof 类

1.抽象(abstract)

假的 只有名字没有具体实现

  1. 如果一个类中有抽象方法,那么它的类一定是抽象类。
  2. 抽象类中不一定有抽象方法。
  3. 抽象类是不能实例化的,不能new,但抽象类是有构造方法的,并且可以重载
  4. 抽象类中可以有具体方法和成员变量
  5. 抽象类在被子类继承时,必须实现抽象类的所有抽象方法,否则子类也是抽象类。

代码案例:计算体积

public class JuXing extends Ban{
    private double a;
    private  double b;
    //private double h;

    public JuXing(double a, double b, double h) {
        super(h);
        this.a = a;
        this.b = b;
        //this.h = h;
    }

    @Override
    public double mianJi() {
        return a*b;
    }

    /*@Override
    public double tiJi(){
        double mianJi = a*b;
        return mianJi*getH();
    }*/
}
public class SanJiao extends Ban{
    private double a;
    private double b;
    private double c;
    //private double h;

    public SanJiao(double a, double b, double c, double h) {
        super(h);
        this.a = a;
        this.b = b;
        this.c = c;
        //this.h = h;
    }

    @Override
    public double mianJi() {
        double p = (a+b+c)/2;
        return Math.sqrt(p*(p-a)*(p-b)*(p-c));
    }

    /*@Override
    public double tiJi(){
        double p = (a+b+c)/2;
        double mianJi = Math.sqrt(p*(p-a)*(p-b)*(p-c));
        return mianJi*getH();
    }*/
}
public class Yuan extends Ban{
    private double c;
    //private double h;

    public Yuan(double c, double h) {
        super(h);
        this.c = c;
        //this.h = h;
    }

    @Override
    public double mianJi() {
        double r = (c/Math.PI)/2;
        return r*r*Math.PI; //Math.pow(r,2)*Math.PI;
    }

    /*@Override
    public double tiJi(){
        double r = (c/Math.PI)/2;
        double s = r*r*Math.PI; //Math.pow(r,2)*Math.PI;
        return s*getH();
    }*/
}
public abstract class Ban {

    public abstract double mianJi();

    public double tiJi(){
        return mianJi()*h;  // 多态
    }

    private double h;

    public double getH() {
        return h;
    }

    public void setH(double h) {
        this.h = h;
    }

    public Ban() {
    }

    public Ban(double h) {
        this.h = h;
    }
}
public class Test {
    public static void main(String[] args) {
        //Object[] bans = new Object[3];

        Ban[] bans = new Ban[3];

        bans[0] = new JuXing(1.3,0.7,0.5);
        bans[1] = new Yuan(3.6,0.7);
        bans[2] = new SanJiao(1.2,1.1,0.7,0.4);

        double tiJiHe = 0.0;

        // 怎么计算体积和
        for (Ban obj: bans) {

            tiJiHe+=obj.tiJi();

            /*if (obj instanceof JuXing){     // 判断一个变量是不是某种类型
                System.out.println("juxing.......");
                tiJiHe += ((JuXing)obj).tiJi();     // 强转:往下转型
            }
            if (obj instanceof Yuan){     // 判断一个变量是不是某种类型
                System.out.println("yuan........");
                tiJiHe += ((Yuan)obj).tiJi();     // 强转:往下转型
            }
            if (obj instanceof SanJiao){     // 判断一个变量是不是某种类型
                System.out.println("sanjiao........");
                tiJiHe += ((SanJiao)obj).tiJi();     // 强转:往下转型
            }*/
        }

        System.out.println(tiJiHe);
    }
}

2.接口(interface)

使用interface修饰的类就是接口,接口的本质也是类,比抽象类还抽象的类

接口比抽象类 假的更彻底

子类继承接口时,子类必须实现接口中的所有方法,否则子类也只能是抽象接口,
接口不能实例化,
接口中没有构造方法

接口的意义

  • 规定协议
  • 模拟多继承 接口是:is-like

接口种所有方法默认是public abstract
当子类实现一个接口时,子类实现接口的所有方法

1.案例1

使用了接口隔离原则

public interface EatAble {
    void eat();
}
public interface SayAble {
    void say();
}
public abstract class Pet {

    //public abstract void eat();

    private Date bron;
    private String type;

    public Pet() {
    }

    public Pet(Date bron, String type) {
        this.bron = bron;
        this.type = type;
    }

    public Date getBron() {
        return bron;
    }

    public void setBron(Date bron) {
        this.bron = bron;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
public class Dog extends Pet implements EatAble,SayAble{
    private String name;

    @Override
    public void eat() {
        System.out.println(name+"在坑骨头!");
    }

    @Override
    public void say() {
        System.out.println(getType()+"叫妈妈了");
    }

    public Dog() {
    }

    public Dog(Date bron, String type, String name) {
        super(bron, type);
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Pig extends Pet implements EatAble{

    private double weight;

    @Override
    public void eat() {
        System.out.println(super.getType()+"的猪的体重为:"+weight);
    }

    public Pig() {
    }

    public Pig(Date bron, String type, double weight) {
        super(bron, type);
        this.weight = weight;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }
}
public abstract class Person {

    //public abstract void eat();

    private Date bron;
    private String name;

    public Person() {
    }

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

    public Date getBron() {
        return bron;
    }

    public void setBron(Date bron) {
        this.bron = bron;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class Student extends Person implements EatAble,SayAble{
    public String gender;

    @Override
    public void eat() {
        System.out.println(getName()+"同学在吃牛排,性别是:"+gender);
    }

    @Override
    public void say() {
        System.out.println(getName()+"同学是:"+gender+"  生");
    }

    public Student() {
    }

    public Student(Date bron, String name, String gender) {
        super(bron, name);
        this.gender = gender;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}
public class Teacher extends Person implements EatAble,SayAble{
    private String zhuanye;

    @Override
    public void eat() {
        System.out.println(getName()+"老师在吃龙虾,教的专业是:"+zhuanye);
    }

    @Override
    public void say() {
        System.out.println(getName()+"正在讲:"+zhuanye);
    }

    public Teacher() {
    }

    public Teacher(Date bron, String name, String zhuanye) {
        super(bron, name);
        this.zhuanye = zhuanye;
    }

    public String getZhuanye() {
        return zhuanye;
    }

    public void setZhuanye(String zhuanye) {
        this.zhuanye = zhuanye;
    }
}
public class Test {
    public static void main(String[] args) {
        Object[] objects = new Object[4];
        objects[0] = new Teacher(new Date(),"张老师","大数据");
        objects[1] = new Student(new Date(),"韩美","女");
        objects[2] = new Dog(new Date(),"哈士奇","贝贝");
        objects[3] = new Pig(new Date(),"荷兰猪",334.3);

        for (int i = 0; i < objects.length; i++) {
            if (objects[i] instanceof EatAble){
                EatAble obj = (EatAble) objects[i];   // 往下转型,不安全
                obj.eat();        // 多态
            }
            /*if (objects[i] instanceof Pet){
                Pet obj = (Pet) objects[i];     // 往下转型,不安全
                obj.eat();
            }*/
            if (objects[i] instanceof SayAble){
                SayAble obj = (SayAble) objects[i];
                obj.say();        // 多态
            }

        }
    }
}

2.案例2:打印墨盒

使用了里氏替换原则

// 当子类实现一个接口时,子类实现接口的所有方法
public class A4 implements Pager{

    @Override
    public String getTypeInfo() {

        return "A4纸张";
    }
}
public class B5 implements Pager{
    @Override
    public String getTypeInfo() {
        return "B5纸张";
    }
}
public interface Pager {
    String getTypeInfo();
}
public class BlackWhiteInkBox implements InkBox{
    @Override
    public String getTypeInfo() {
        return "黑白墨盒";
    }
}
public class MutiColorInkBox implements InkBox{
    @Override
    public String getTypeInfo() {
        return "彩色墨盒";
    }
}
public interface InkBox {
    String getTypeInfo();
}
public class Printer {

    // 打印机在定义成员时,使用的是接口,而不是具体类型。
    // 这种编程思考的现象称为:面向接口编程
    // 接口类型:InkBox
    private  InkBox inkBox;
    private Pager pager;

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

    public void setPager(Pager pager) {
        this.pager = pager;
    }

    public void print(String helloWorld) {
        System.out.println("使用"+inkBox.getTypeInfo()+"在"+pager.getTypeInfo()+"打印:"+helloWorld);
    }
}
public class Test {
    public static void main(String[] args) {

        // 创建一台打印机
        Printer p = new Printer();
        // 为打印机安装黑白墨盒
        p.setInkBox(new BlackWhiteInkBox());
        // 装上A4纸张
        p.setPager(new A4());
        // 开始打印
        p.print("helloWorld2222222222");
        System.out.println("要换纸张吗?");
        // 换纸张为B5,不用换打印机
        p.setPager(new B5());
        // 希望在新类型的纸张上打印B5
        p.print("helloWorld11111111111");
        // 换墨盒为 彩色
        System.out.println("换墨");
        p.setInkBox(new MutiColorInkBox());
        p.print("helloWorld3333333333333333");

    }

}

3.案例3:手机功能案例

使用接口隔离原则

public interface CallPhoneable {
    public void callPhone(String phoneNum);
}
public interface Sendable {
    public void sendMsg(String msg);
}
public class OldPhone extends Phone implements CallPhoneable,Sendable{
    public OldPhone(String s) {
        super(s);
    }
    @Override
    public void callPhone(String phoneNum) {
        System.out.println(getNo()+"正在呼叫"+phoneNum);
    }
    @Override
    public void sendMsg(String msg) {
        System.out.println(getNo()+"正在发短信,内容是:"+ msg);
    }
}
public class BBPhone extends Phone implements Sendable{
    public BBPhone(String no) {
        super(no);
    }

    @Override
    public void sendMsg(String msg) {
        System.out.println(msg+"正在发短信");
    }
}
public class Phone /*implements Sendable,CallPhoneable*/{
    public String no;

    public Phone(String no) {
        this.no = no;
    }

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }
    /*public void run() {
        // 发短信
        sendMsg("我爱你");
        callPhone("c123456789");
    }
    @Override
    public void sendMsg(String msg) {
        System.out.println("发送消息"+msg);
    }
    @Override
    public void callPhone(String phoneNum) {
        System.out.println("拨打"+phoneNum+"电话");
    }*/
}
public class Test {
    public static void main(String[] args) {
        /*Phone p = new Phone();
        // 发短信
        p.run();*/

        Phone p = new OldPhone("010334324");
        // 要理解  为什么正确  因为OldPhone具有打电话的能力,也就是相当于继承了
        //CallPhoneable c = new OldPhone("234");    // 泛化
        // 为什么不对  因为BBPhone不具备打电话的功能,  也就是相当于没继承
        //CallPhoneable cc = new BBPhone("3");

        if (p instanceof CallPhoneable){
            ((CallPhoneable) p).callPhone("0101111111111");
        }else {
            System.out.println("不具备打电话的功能!");
        }
        if (p instanceof Sendable){
            ((Sendable) p).sendMsg("我爱你");
        }else {
            System.out.println("不具备发短信的功能");
        }
    }
}

3.面向对象的设计原则(8种)

接口隔离原则

里氏替换原则

4.接口继承接口

主要用在接口组合这种场景下

interface 接口名 extends  接口1,接口2...{

}

代码案例:

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

interface A{
    void foo();
}
interface B{
    void show();
}
// 组合A和B    组合接口:叫接口继承
// 类不能继承接口,接口可以继承多个接口
interface F extends A,B{

}
class C implements F{

    @Override
    public void foo() {

    }

    @Override
    public void show() {

    }
}

5.static(静态)

final 可以修饰类,方法,变量(常量)

static 修饰类,方法,成员变量(共享量),

代码案例:

public class Test {
    /**
     * static 学习
     * java 时面向对象的设计语言,但是保留了非面向对象的内容
     *
     * static 与对象无关
     *
     * static  main方法,这是一个与对象没有关系的方法,称呼为静态方法
     * 调用时,不依赖对象,只依赖类
     * 由于static与对象无关,所以static方法中永远不能出现this
     *
     * foo方法  与对象息息相关的方法,称呼为成员方法或者对象方法
     * 调用时,必须依赖对象
     * 所以所有的对象方法都隐含了一个变量  这个变量名是:this
     * 在本质上Java对象方法都应该是有参数的
     *
     * @param args
     */
    int i = 19;     // 成员变量,成员即对象

    public static void main(String[] args) {
        System.out.println(args.length);
        System.out.println(args[0]);
        //System.out.println(args[1]);
        //foo();
        new Test().foo();
    }

    public void foo(Test this){
        System.out.println("hello static");
    }

    public void show(){
        System.out.println("dfsfs");
        foo();
    }

    public Test myself(){
        return this;
    }
}

静态变量

public class Test2 {
    int i;
    static int n;

    public static void main(String[] args) {
        Test2 t = new Test2();
        Test2 t2 = new Test2();
        t.i++;
        System.out.println(t.i);        //1
        System.out.println(t2.i);       //0
        System.out.println("---------");
        Test2.n++;
        System.out.println(Test2.n);    //1
        System.out.println(Test2.n);    //1
    }
}

6.变量有几类?

成员变量
局部变量

7.内部类

内部类有3种:静态内部类,成员内部类,匿名内部类
内部类分三种:

  • 静态内部类,:使用时和静态变量,静态方法一样,依赖外部类使用
  • 成员内部类,:使用时和成员变量,成员方法一样,必须依赖对象
  • 匿名内部类 : 没有名字的类,只能使用一次

有两个this:一个外部类this,一个内部类this
外部类的this是外部类名.this
内部类可以访问外部类的private修饰的东西,
外部类也可以访问内部类private修饰的东西

代码案例

public class Test {
    /**
     * 内部类学习
     * 顾名思义:在类的内部定义类
     *
     * 内部类分三种:
     * 静态内部类,:使用时和静态变量,静态方法一样,依赖外部类使用
     * 成员内部类,:使用时和成员变量,成员方法一样,必须依赖对象
     * 匿名内部类 : 没有名字的类,只能使用一次
     *
     * @param args
     */
    public static void main(String[] args) {
        // 成员内部类的创建必须依赖外部类对象
        new Test().new A();
        // 静态内部类 :这个地方new的是B,而不是Test
        new Test.B();
        // 定义匿名内部类,并调用say方法
        Person p = new Person(){
            @Override
            public void say() {
                System.out.println("匿名内部类。。。。。");
            }
        };      // 泛化
        p.say();    // 多态

        // 匿名内部类
        Eatable e = new Eatable() {
            @Override
            public void eat() {
                System.out.println("学会编程");
            }
        };
        e.eat();

        // lambda表达式  函数  lambda表达式只能拥有一个接口中只有一个对象
        Eatable e2 = () -> System.out.println("牛不牛");
        e2.eat();
    }
    // 成员内部类
    class A{

    }
    // 静态内部类
    static class B{

    }
}

abstract class Person{
    public abstract void say();
}

interface Eatable{
    void eat();
}

8.案例:多态数组

public class MyArray {
    private int count;
    //private String[] ds = new String[3];
    private Jie head;
    private Jie tail;

    public void add(String s) {
        count++;
        Jie jie = new Jie(s);
        // 判断头部 == null
        if (head == null){
            head = jie;     // 让创建的车厢为头部(头节)
        }else {
            tail.next = jie;    // 让这节跟在下一节
        }
        tail = jie; // 型车厢就是最后一节车厢
    }

    public int size() {

        return count;
    }

    public String get(int i) {
        Jie p = head;
        for (int j = 0; j < i; j++) {
            p = p.next;
        }
        return p.data;
    }

    // 私有内部类   只应用于该类,不想让别人用
    private class Jie{
        private String data;
        private Jie next;

        public Jie(String s) {
            this.data = s;
        }
    }
}
复制public class Test {
    public static void main(String[] args) {
        /*
            数组:数据个数是不会变化的
            自定义一种数据结构:动态数组  链表式数据结构 使用引用
         */
        MyArray datas = new MyArray();
        datas.add("abc");   // 模拟的就是   数组[index] = 值;
        //datas.add("123");
        //datas.add("xgz");
        datas.add("345");
        //System.out.println(datas.add("erw"));
        //System.out.println(datas.get(1));

        for (int i = 0; i < datas.size(); i++) {// datas.size()  模拟的就是  数组.length
            System.out.println(datas.get(i));      // 模拟数组,按下标取数据
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值