zoukankan      html  css  js  c++  java
  • 06 面向对象:多态&抽象类&接口&权限修饰符&内部类

    多态:

    /*
     多态(polymorphic)概述
        * 事物存在的多种形态
     多态前提
        * a:要有继承关系。
        * b:要有方法重写。
        * c:要有父类引用指向子类对象。
    * 成员变量
        * 编译看左边(父类),运行看左边(父类)。
    * 成员方法
        * 编译看左边(父类),运行看右边(子类)。动态绑定
    * 静态方法
        * 编译看左边(父类),运行看左边(父类)。
        * (静态和类相关,算不上重写,所以,访问还是左边的)
        * 只有非静态的成员方法,编译看左边,运行看右边
    
    */
    class Demo_Polymorphic {
        public static void main(String[] args)
        {
            Animal a = new Cat(); // 父类引用指向子类对象
            a.eat(); // 猫吃鱼 // 如果父类没有eat方法就会报错,编译看左边(父类)
            System.out.println(a.num); // 10 成员变量,运行看父类
            a.method(); // Animal static method ,相当于Animal.method()
        }
    }
    class Animal
    {
        int num = 10;
        public void eat(){
            System.out.println("动物吃饭");
        }
        public static void method(){
            System.out.println("Animal static method");
        }
    }
    class Cat extends Animal
    {
        int num = 20;
        public void eat(){
            System.out.println("猫吃鱼");
        }
        public static void method(){
            System.out.println("Cat static method");
        }
    }
    /*
    * A:多态的好处
        * a:提高了代码的维护性(继承保证)
        * b:提高了代码的扩展性(由多态保证)
    * B:可以当作形式参数,可以接收任意子类对象
    * C:多态的弊端
        * 不能使用子类的特有属性和行为。
    */
    class Demo_Polymorphic1 {
        public static void main(String[] args)
        {
            Animal a = new Cat();// 向上转型
            a.eat();
            Cat c = (Cat)a; //向下转型
            c.method();
    
        //    Animal a2 = new Dog();
            methods(new Dog());
        }
        public static void methods(Animal a){ // 作形式参数
            if (a instanceof Cat)
            {
                Cat c = (Cat)a;
                c.method();
            }
            else if (a instanceof Dog)
            {
                Dog d = (Dog)a;    
                d.method();
            }else{
                a.eat();
            }
        }
    }
    class Animal
    {
        public void eat(){
            System.out.println("动物吃饭");
        }
    }
    class Cat extends Animal
    {
        public void eat(){
            System.out.println("猫吃鱼");
        }
        public void method(){
            System.out.println("猫捉老鼠");
        }
    
    }
    class Dog extends Animal
    {
        public void eat(){
            System.out.println("狗吃肉");
        }
        public void method(){
            System.out.println("狗看门");
        }
    }
    多态的好坏

    抽象的特点:

    /*
    抽象类特点
        * a:抽象类和抽象方法必须用abstract关键字修饰
            * abstract class 类名 {}
            * public abstract void eat();
        * b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
        * c:抽象类不能实例化那么,抽象类如何实例化呢?
            * 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
        * d:抽象类的子类
            * 要么是抽象类
            * 要么重写抽象类中的所有抽象方法
    *
        * 抽象类特点B:抽象类特点
        * a:抽象类和抽象方法必须用abstract关键字修饰
            * abstract class 类名 {}
            * public abstract void eat();
        * b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类或者是接口
        * c:抽象类不能实例化那么,抽象类如何实例化呢?
            * 按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
        * d:抽象类的子类
            * 要么是抽象类
            * 要么重写抽象类中的所有抽象方法
    */
    class Demo_Abstract {
        public static void main(String[] args)
        {
        //    Animal a = new Animal();//错误: Animal是抽象的; 无法实例化
            new Cat().method();
        }
    }
    abstract class Animal
    {
        public abstract void method();
        public void eat(){
            System.out.println("eat");
        }
    }
    class Cat extends Animal
    {
        public void method(){
            System.out.println("捉老鼠");
        }
    }


    抽象类的成员特点:
    * 抽象类的成员特点
        * a:成员变量:既可以是变量,也可以是常量。abstract是否可以修饰成员变量?不能修饰成员

    变量
        * b:构造方法:有。
            * 用于子类访问父类数据的初始化。
        * c:成员方法:既可以是抽象的,也可以是非抽象的。
    * 抽象类的成员方法特性:
        * a:抽象方法 强制要求子类做的事情。
        * b:非抽象方法 子类继承的事情,提高代码复用性。

    一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
        * 可以
        * 这么做目的只有一个,就是不让其他类创建本类对象,交给子类完成
    abstract不能和哪些关键字共存
        abstract和static
        被abstract修饰的方法没有方法体
        被static修饰的可以用类名.调用,但是类名.调用抽象方法是没有意义的
        abstract和final
        被abstract修饰的方法强制子类重写
        被final修饰的不让子类重写,所以他俩是矛盾
        abstract和private
        被abstract修饰的是为了让子类看到并强制重写
        被private修饰不让子类访问,所以他俩是矛盾的

    abstract class Demo {
        //public static abstract void print();        //错误: 非法的修饰符组合: abstract
    
    和static
        //public final abstract void print();        //错误: 非法的修饰符组合: abstract
    
    和final
        private abstract void print();                //错误: 非法的修饰符组合:
    
    abstract和private
    }


    接口:

    /*
    * A:接口概述
        * 从狭义的角度讲就是指java中的interface
        * 从广义的角度讲对外提供规则的都是接口
    * B:接口特点
        * a:接口用关键字interface表示    
            * interface 接口名 {}
        * b:类实现接口用implements表示
            * class 类名 implements 接口名 {}
        * c:接口不能实例化
            * 按照多态的方式来实例化。
        * d:接口的子类
            * a:可以是抽象类。但是意义不大。
            * b:可以是具体类。要重写接口中的所有抽象方法。(推荐方案)
    */
    class Demo_Interface {
        public static void main(String[] args)
        {
        //    Inter i = new Inter();//错误: Inter是抽象的; 无法实例化
            Inter i = new A(); // 按照多态的方式实例化
            i.print();
    
            new Y().print();
        }
    }
    interface Inter
    {
        public abstract void print(); // 接口中的方法都是抽象的
    }
    class A implements Inter
    {
        public void print(){
            System.out.println("a");
        }
    }
    /*
    接口成员特点
        * 成员变量;只能是常量,并且是静态的并公共的。
                * 默认修饰符:public static final
                * 建议:自己手动给出。
        * 构造方法:接口没有构造方法。
        * 成员方法:只能是抽象方法。
                * 默认修饰符:public abstract
                * 建议:自己手动给出。
    */
    interface X
    {
        public static final int num = 10;
        public abstract void print();
    
    //    public X(){}//接口没有构造方法
    
    //    public void print(){} // 只能是抽象方法
    
    }
    class Y implements X
    {
        public Y(){
            super();  // 父类object
        }
        public void print(){
            System.out.println(num);
        }
    
    }
    
    class Demo3_Interface {
        public static void main(String[] args) {
            System.out.println("Hello World!");
        }
    }
    
    /*
    * 类与类,类与接口,接口与接口的关系
        * a:类与类:
            * 继承关系,只能单继承,可以多层继承。
        * b:类与接口:
            * 实现关系,可以单实现,也可以多实现。
            * 并且还可以在继承一个类的同时实现多个接口。
        * c:接口与接口:
            * 继承关系,可以单继承,也可以多继承。
    */
    
    interface InterA {
        public abstract void printA();
    }
    
    interface InterB {
        public abstract void printB();
    }
    
    interface InterC extends InterB,InterA {
    }
    //class Demo implements InterA,implements InterB {        //这么做不允许是非法的
    class Demo extends Object implements InterA,InterB {
        public void printA() {
            System.out.println("printA");
        }
    
        public void printB() {
            System.out.println("printB");
        }
    }
    class Demo3_Interface {
        public static void main(String[] args) {
            System.out.println("Hello World!");
        }
    }
    
    /*
    * A:类与类,类与接口,接口与接口的关系
        * a:类与类:
            * 继承关系,只能单继承,可以多层继承。
        * b:类与接口:
            * 实现关系,可以单实现,也可以多实现。
            * 并且还可以在继承一个类的同时实现多个接口。
        * c:接口与接口:
            * 继承关系,可以单继承,也可以多继承。
    */
    
    interface InterA {
        public abstract void printA();
    }
    
    interface InterB {
        public abstract void printB();
    }
    
    interface InterC extends InterB,InterA {
    }
    //class Demo implements InterA,implements InterB {        //这么做不允许是非法的
    class Demo extends Object implements InterA,InterB {
        public void printA() {
            System.out.println("printA");
        }
    
        public void printB() {
            System.out.println("printB");
        }
    }
    
    class Demo3_Interface {
        public static void main(String[] args) {
            System.out.println("Hello World!");
        }
    }
    
    /*
    * A:类与类,类与接口,接口与接口的关系
        * a:类与类:
            * 继承关系,只能单继承,可以多层继承。
        * b:类与接口:
            * 实现关系,可以单实现,也可以多实现。
            * 并且还可以在继承一个类的同时实现多个接口。
        * c:接口与接口:
            * 继承关系,可以单继承,也可以多继承。
    */
    
    interface InterA {
        public abstract void printA();
    }
    
    interface InterB {
        public abstract void printB();
    }
    
    interface InterC extends InterB,InterA {
    }
    //class Demo implements InterA,implements InterB {        //这么做不允许是非法的
    class Demo extends Object implements InterA,InterB {
        public void printA() {
            System.out.println("printA");
        }
    
        public void printB() {
            System.out.println("printB");
        }
    }
    
    class Demo3_Interface {
        public static void main(String[] args) {
            System.out.println("Hello World!");
        }
    }
    
    /*
    * A:类与类,类与接口,接口与接口的关系
        * a:类与类:
            * 继承关系,只能单继承,可以多层继承。
        * b:类与接口:
            * 实现关系,可以单实现,也可以多实现。
            * 并且还可以在继承一个类的同时实现多个接口。
        * c:接口与接口:
            * 继承关系,可以单继承,也可以多继承。
    */
    
    interface InterA {
        public abstract void printA();
    }
    
    interface InterB {
        public abstract void printB();
    }
    
    interface InterC extends InterB,InterA {
    }
    //class Demo implements InterA,implements InterB {        //这么做不允许是非法的
    class Demo extends Object implements InterA,InterB {
        public void printA() {
            System.out.println("printA");
        }
    
        public void printB() {
            System.out.println("printB");
        }
    }

    抽象类和接口的区别

    * 成员区别
        * 抽象类:
            * 成员变量:可以变量,也可以常量
            * 构造方法:有
            * 成员方法:可以抽象,也可以非抽象
        * 接口:
            * 成员变量:只可以常量
            * 成员方法:只可以抽象
    
    * 关系区别
        * 类与类
            * 继承,单继承
        * 类与接口
            * 实现,单实现,多实现
        * 接口与接口
            * 继承,单继承,多继承
    
    * 设计理念区别
        * 抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
        * 接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。


    为什么要有包:
        * 将字节码(.class)进行分类存放
        * 包其实就是文件夹

    包的定义及注意事项
    * A:定义包的格式
        * package 包名;
        * 多级包用.分开即可
    * B:定义包的注意事项
        * A:package语句必须是程序的第一条可执行的代码
        * B:package语句在一个java文件中只能有一个
        * C:如果没有package,默认表示无包名

    如何编译运行带包的类:
        * a:javac编译的时候带上-d即可
            * javac -d . HelloWorld.java
        * b:通过java命令执行。
            * java 包名.HellWord
    import关键字的概述和使用:
    * 为什么要有import
            * 其实就是让有包的类对调用者可见,不用写全类名了
    * 导包格式
        * import 包名;
        * 注意:
              这种方式导入是到类的名称。
              虽然可以最后写*,但是不建议。


    四种权限修饰符:

      本类           同一个包下(子类和无关类)  不同包下(子类) 不同包下(无关类)
    private      Y      
     默认         Y Y    
    protected    Y Y Y  
    public         Y Y Y Y


    类及其组成所使用的常见修饰符:

    * A:修饰符:
        * 权限修饰符:private,默认的,protectedpublic
        * 状态修饰符:staticfinal
        * 抽象修饰符:abstract
    * B:类:
        * 权限修饰符:默认修饰符,public
        * 状态修饰符:final
        * 抽象修饰符:abstract
    
        * 用的最多的就是:public
    
    * C:成员变量:
        * 权限修饰符:private,默认的,protectedpublic
        * 状态修饰符:staticfinal
    
        * 用的最多的就是:private
    
    * D:构造方法:
        * 权限修饰符:private,默认的,protectedpublic
    
        * 用的最多的就是:public
    
    * E:成员方法:
        * 权限修饰符:private,默认的,protectedpublic
        * 状态修饰符:staticfinal
        * 抽象修饰符:abstract
    
        * 用的最多的就是:public
    
    * F:除此以外的组合规则:
        * 成员变量:public static final 接口
        * 成员方法:
            * public static
            * public abstract
            * public final



    内部类访问特点
        * a:内部类可以直接访问外部类的成员,包括私有。
        * b:外部类要访问内部类的成员,必须创建对象。
        * 外部类名.内部类名 对象名 = 外部类对象.内部类对象;
    
    class Demo_Inner {
        public static void main(String[] args)
        {
            Outer.Inner oi = new Outer().new Inner();
            oi.method();
            // 访问内部类的私有使用
            Outer2 o = new Outer2();
            o.print();
            // 访问静态成员内部类
            Outer3.Inner o3 = new Outer3.Inner();
            o3.method();
    
            Outer4.Inner.method();
        }
    }
    class Outer
    {
        private int num = 10;
        class Inner
        {
            public void method(){
                System.out.println(num);
            }
        }
    }
    // 内部类的私有使用
    class Outer2
    {
        private int num = 10;
        private class Inner
        {
            public void method(){
                System.out.println(num);
            }
        }
        public void print(){
            new Inner().method();
        }
    }
    /*
    静态成员内部类
    * 成员内部类被静态修饰后的访问方式是:
        * 外部类名.内部类名 对象名 = 外部类名.内部类对象;
    */
    class Outer3
    {
        static class Inner
        {
            public void method(){
                System.out.println("static");
            }
        }
    }
    class Outer4
    {
        static class Inner
        {
            public static void method(){
                System.out.println("static");
            }
        }
    }


    使用已知的变量,在控制台输出30,20,10。
      

     // 内部类之所以能获得外部类的成员,是因为他能获取到外部类的引用 外部类名.this
            class Outer {
                public int num = 10;
                class Inner {
                    public int num = 20;
                    public void show() {
                        int num = 30;
                        System.out.println(num);
                        System.out.println(this.num);
                        System.out.println(Outer.this.num);
                    }
                }
            }
            class InnerClassTest {
                public static void main(String[] args) {
                    Outer.Inner oi = new Outer().new Inner();
                    oi.show();
                }    
            }
    
    class Demo_InnerClass {
        public static void main(String[] args)
        {
            Outer o = new Outer();
            o.method();
        }
    }
    // 局部内部类
    class Outer
    {
        public void method(){
            final int num = 10; //  局部内部类访问局部变量必须用final修饰
            class Inner
            {
                public void print(){
                    System.out.println(num);
                }
            }
            new Inner().print();
        }
        /*
        public void Test(){
            new Inner().print();// 错误,局部内部类,只能在其所在的方法中访问
        }
        */
    }
    
    /*
        * 局部内部类在访问他所在方法中的局部变量必须用final修饰,为什么?
            因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周
    
    期是一样的,当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部
    
    变量,就没有了,如果用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池的常量还在,也可
    
    以继续使用
    
            但是jdk1.8,如果在书写代码时候,没有手动添加,系统底层也会默给你final
    
    */


    匿名内部类:

    /*
    * A:匿名内部类
        * 就是内部类的简化写法。
    * B:前提:存在一个类或者接口
        * 这里的类可以是具体类也可以是抽象类。
    * C:格式:
            new 类名或者接口名(){
                重写方法;
            }
    * D:本质是什么呢?
        * 是一个继承了该类或者实现了该接口的子类匿名对象。
    */
    class Demo_InnerClass2 {
        public static void main(String[] args)
        {
            new Outer().method();
        }
    }
    interface Inner
    {
        public abstract void print();
    }
    class Outer
    {
        public void method(){
            new Inner(){
                public void print(){
                    System.out.println("Hello World!");
                }
            }.print();
        }
    }
    // 匿名内部类重写多个方法调用
    // 建议匿名类只针对重写一个方法时候使用
    interface Inner2
    {
        public abstract void print1();
        public abstract void print2();
    }
    class Outer2
    {
        public void method(){
            Inner2 i = new Inner2(){  // 父类引用指向子类对象
                public void print1(){
                    System.out.println("print1");
                }
                public void print2(){
                    System.out.println("print1");
                }
                /*
                public void print3(){
                    System.out.println("print3");
                }
                */
            };
            i.print1();
            i.print2();
        //    i.print3(); // 匿名内部类是不能向下转型的,因为没有自类类名
        }
    }
    class Test_NoNameInnerClass {
        public static void main(String[] args)
        {
            Outer.method().show();
            // 相当于
            Inter i = Outer.method();
            i.show();
        }
    }
    interface Inter
    {
        void show();
    }
    class Outer
    {
        public static Inter method(){
            return new Inter(){
                public void show(){
                    System.out.println("Hello World!");
                }
            };
        }
    }
    /*
    Hello World!
    */


    重写补充:返回值类型是子父类

    /*
    重写:子父类出现了一模一样的方法
    (注意:返回值类型可以是子父类)
    */
    class Demo_FaSonClass {
        public static void main(String[] args)
        {
            
        }
    }
    class Person
    {
        public void print(){
            System.out.println("Hello World!");
        }
    }
    class Person2 extends Person  
    {
        public void print(){
            System.out.println("Hello World!2");
        }
    }
    class Father
    {
        public Person method(){
            return new Person();  //Person与Person2 是子父类
        }
    }
    class Son extends Father
    {
        public Person2 method(){
            return new Person2(); //Person与Person2 是子父类
        }
    }
    View Code
  • 相关阅读:
    新学期随笔——脚踏实地
    买书方案
    课程总结和建议
    梦断代码阅读笔记03
    梦断代码阅读笔记02
    构建之法阅读笔记06
    【洛谷5284】[十二省联考2019] 字符串问题(后缀树优化建边)
    【BZOJ3514】Codechef MARCH14 GERALD07加强版(LCT_主席树)
    【BZOJ1487】[HNOI2009]无归岛(仙人掌 DP)
    【洛谷3239_BZOJ4008】[HNOI2015] 亚瑟王(期望 DP)
  • 原文地址:https://www.cnblogs.com/fly-book/p/9844266.html
Copyright © 2011-2022 走看看