面向对象(多态与内部类)

多态

多态的概述:多态是继封装,继承之后,面向对象的第三大特性。是指同一行为,具有多个不同表现形式,为多态

举个生活栗子:生活中,比如跑的动作,小猫、小狗和大象,跑起来是不一样的。再比如飞的动作,昆虫、鸟类和飞机,飞起来也是不一样的。可见,同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。

java实现多态条件:

  • 继承:在多态中必须存在有继承关系的子类和父类
  • 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法
  • 向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才既能可以调用父类的方法,又能调用子类的方法

代码简略实现:

public class Dome01 {
    public static void main(String[] args) {
        Fu fu = new Fu();  //创建父类对象
        fu.print();        //我们可以调用父类的公共方法print不能访问name私有方法
        
        Zi zi = new Zi();  //创建子类对象
        zi.print();        //子类自动继承父类的print()方法,但是子类里也写了一个print方法,所以属于重写父类方法
        zi.run();          //子类继承父类可继承的方法或变量,所以可以通过子类调用run
        
        //多态----------------
        Fu zi2 = new Zi();    //创建子类对象,使用父类来承接
        zi2.print();          //和上面的子类对象调用一样,上面子类能调用发下面也能调用
        zi.run();
    }
}

class Fu {// 定义父类方法
    public void print() {
        System.out.println("我是父类的输出方法");
    }

    private void name() {
        System.out.println("我是父类的私有方法");
    }
    
    public void run() {
        System.out.println("我是父类的run方法");
    }
}

class Zi extends Fu { // 定义子类
    // 子类方法一
    @Override
    public void print() {
        System.out.println("我是子类的输出方法");
    }

    private void name() {
        System.out.println("我是子类的私有方法");
    }

}

虽然使用下面多态调用效果一样,但是调用的过程是有区别的

  • 成员变量:编译看左边(父类),运行看左边(父类)   所有的成员变量取决于编译时类型

  • 成员方法:编译看左边(父类),运行看右边(子类)   所有的成员方法取决于运行时类型

  • 静态方法:编译看左边(父类),运行看左边(父类)   所有的静态方法取决于编译时类型

代码解释:

public class Dome02 {
    public static void main(String[] args) {
            Fu1 zi1 = new Zi1();
            System.out.println(zi1.a);  //输出的值为0,调用成员方法是编译时看父类的成员变量,运行时也运行父类的成员变量
            zi1.name();  //调用成员方法时,编译时,先看父类有没有该成员方法,如果有,就去看子类有没有,如果也有就执行子类的
            zi1.name2(); // 由于name02是静态方法,所以,调用时编译是看的是父类,所以运行时也会运行父类的,
            
            
            //调用静态方法和成员变量,静态的是属于各自类的不能继承也不能被重写
            Fu1.name2(); System.out.println(Fu1.b);
            Zi1.name2(); System.out.println(Zi1.b);
    }
}

class Fu1 {
    int a = 0;
    static int b = 1;

    public void name() {
        System.out.println("我是父类普通成员方法");
    }

    public static void name2() {
        System.out.println("我是父类静态成员方法");
    }
}

class Zi1 extends Fu1 {
    int a = 22;
    static int b = 11;

    @Override
    public void name() {
        System.out.println("我是子类普通成员方法");
    }

    public static void name2() { // 静态方法不能重写
        System.out.println("我是子类的静态成员方法");
    }
}

在调用成员方法时,子类如果没有重写,会默认继承父类的,所以运行依旧子类中的name()方法,但本质上这个name()方法依旧是父类的,但子类重写后,它的本质就变量,相当于子类从父类继承来了一块宝石,然后子类经过一系列的打磨,雕刻,它变成了一个工艺品,这个时候,这个工艺品就是子类独有的而并非还是原来的那个宝石。注:父类的方法在子类重写后仍可以通过父类对象调用

多态的好处: 可以使程序编写的更简单,并有良好的扩展。

引用类型的转型:

 转型分为向上转型和向下转型两种。

向上转型 :多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。当父类引用指向一个子类对象时,便是向上转型。

父类类型 变量名 = new 子类类型(); 
如:Animal a = new Cat();

向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。

子类类型 变量名 = (子类类型) 父类变量名; 
如:Cat c =(Cat) a;

instanceof关键字:

有时候,在转换类型的时候,程序员会看不到源码,所以我们需要强转时,不知道该往哪一个子类去转换,就会引发ClassCastException异常,为了处理这一个问题java提供了instanceof关键字。(类似于判断的意思) 演示如下:

public class MyTest3 { 
    public static void main(String[] args) { 
        // 向上转型 
        Animal a = new Cat(); 
        a.eat(); // 调用的是 Cat 的 eat 
        // 向下转型 
        if (a instanceof Cat){ 
            Cat c = (Cat)a; 
            c.catchMouse(); // 调用的是 Cat 的 catchMouse 
        } else if (a instanceof Dog){ 
            Dog d = (Dog)a; 
            d.watchHouse(); // 调用的是 Dog 的 watchHouse 
        } 
    } 
}

内部类

  内部类:顾名思义就是内部的类,在一个类A中定义一个类B这个时候   类A就会被称作外部类, 而类B就被称作内部类了。  内部类,有根据所处位置不同,修饰符不同来区分为四大内部类分别是:成员内部类   静态内部类  局部内部类  匿名内部类。

成员内部类:定义在类中方法外的类 ----代码如下:

public class Outer {
    class Inner {
        // 成员内部类
    }
}

成员内部类的注意点:

  • 内部类可以直接访问外部类的成员,包括私有成员。

  • 外部类要访问内部类的成员,必须要建立内部类的对象。

静态内部类:静态内部类是指使用 static 修饰的内部类。----代码如下:

public class Outer {
    static class Inner {
        // 静态内部类
    }
}

静态内部类注意点:

  • 在创建静态内部类的实例时,不需要创建外部类的实例;

  • 静态内部类可以直接访问外部类的静态成员,如果要访问外部类的实例成员,则需要通过外部类的实例去访问。

局部内部类:局部内部类是指在一个方法中局部位置定义的内部类。 ----代码如下:

public class Outer {
    public void method() {
        class Inner {
            // 局部内部类
        }
    }
}

局部内部类注意点:

  • 局部内部类与局部变量一样,不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰;

  • 局部内部类只在当前方法中有效;

  • 局部内部类中不能定义 static 成员。

 匿名内部类:是内部类的简化写法,它的本质是一个 带具体实现的 父类或者父接口的 匿名的 子类对象。 ----代码如下:

 匿名内部类前提:存在一个类或者接口,这里的类可以是具体类也可以是抽象类。

public class Dome03 {
    public static void main(String[] args) {
        // 匿名内部类实现重写普通类的方法
        new test01() {
            @Override
            public void name() {
                // TODO Auto-generated method stub
            }
        };
        // 匿名内部类实现重写抽象类的抽象方法
        new test02() {
            @Override
            public void name() {
                // TODO Auto-generated method stub
            }
        };
        // 匿名内部类实现重写接口的抽象方法
        new test03() {
            @Override
            public void name() {
                // TODO Auto-generated method stub
            }
        };
    }
}

class test01 {
    public void name() {
        System.out.println("");
    }
}

abstract class test02 {
    public abstract void name();
}

interface test03 {
    void name();
}

匿名内部类的作用:

开发中,最常用到的内部类就是匿名内部类了。以接口举例,当你使用一个接口时,似乎得做如下几步操作,

  • 定义子类
  • 重写接口方法
  • 创建子类的对象
  • 调用重写后的方法

我们的目的,最终只是为了调用方法,那么能不能简化一下,把以上四步合成一步呢?匿名内部类就是做这样的快捷方式。

 模板设计模式

 模板设计模式定义:定义一个操作中的算法骨架,将通用步骤以模板形式封装在父类模板中,将具体细节步骤延迟到子类中实现。

如何理解,模板设计模式是将功能的细节封装起来,给外界一个公共的调用模板,我们调用这个模板就能达到想要的需求。比如:我们想在控制台打印三句话:我爱你java,我将好好学习java,我一定会成为一个好的工程师。使用模板设计模式如下:

public class Dome04 {
    public static void main(String[] args) {
        Test test = new Test();
        test.template();   //调用时我们不需要知道代码实现的细节,直接调用模板方法就能完成需求
    }
}

class Test {
    // 细节是什么??? 细节就是三句话
    public void template() { // 定义公共模板
        // 公共模板调用三个细节
        print1();
        print2();
        print3();
    }

    // 使用private封装三个细节
    private void print1() {
        System.out.println("我爱你java");
    }

    private void print2() {
        System.out.println("我将好好学习java");
    }

    private void print3() {
        System.out.println("我一定会成为一个好的工程师");
    }
}

设计模式,属于一种写代码的思想,这里写很是简略,与个人学习有出入,是自己所理解的比较容易懂一些。了解更多细节:https://www.runoob.com/design-pattern/template-pattern.html 

 

个人学习,内容简略

posted @ 2020-08-09 18:08  一生的风景  阅读(245)  评论(0编辑  收藏  举报