10 多态 内部类

对象的多态性:

class 动物
{
}

class 猫 extends 动物
{
}

class 狗 extends 动物
{
}

猫 x = new 猫();
动物 x = new 猫();//一个对象,两种形态.

猫这类事物既具备了猫的形态,又具备着动物的形态,
这就是对象的多态性.
简单说:就是一个对象对应着不同类型.
多态在代码中的体现:
父类或者接口的引用指向其子类的对象.

多态的好处:

提高了代码的扩展性,前期定义的代码可以使用后期的内容,

abstract class Animal
{
    abstract void eat();
}

class Dog extends Animal
{
    void eat()
    {
        System.out.println("啃骨头");
    }
    void lookHome()
    {
        System.out.println("看家");
    }
}

class Cat extends Animal
{
    void eat()
    {
        System.out.println("吃鱼");
    }
    void catchMouse()
    {
        System.out.println("抓老鼠");
    }
}

class Pig extends Animal
{
    void eat()
    {
        System.out.println("饲料");
    }
    void gondDi()
    {
        System.out.println("拱地");
    }

}


class Demo
{
    public static void main(String[] args)
    {
        method(new Dog());
        method(new Cat());
        method(new Pig());
    }
    /*
    public static void method(Cat c)
    {
        c.eat();
    }
    public static void method(Dog d)
    {
        d.eat();
    }
    */
    public static void method(Animal a)
    {
        a.eat();
    }
}

多态的弊端:

  前期定义的内容不能去调用后期子类的特有内容.

多态的前提:

  1.必须有关系,继承,实现.

    2.要有覆盖.

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

        Animal a = new Cat();//自动类型提升,猫对象提升为动物类型.
            //但是特有功能无法访问.
            //作用就是限制对特有功能的访问.
        a.eat();

        //如果还想用具体动物猫的特有功能;
        //你可以将该对象进行向下转型.
        Cat c = (Cat)a;//向下转型的目的是为了使用子类中的特有方法.
        c.eat();
        c.catchMouse();
    }
    /*
    public static void method(Cat c)
    {
        c.eat();
    }
    public static void method(Dog d)
    {
        d.eat();
    }
    */
    public static void method(Animal a)
    {
        a.eat();
    }
}

注意:对于转型,自始至终都是子类对象在做着类型的变化.

Animal a =new Dog();

Cat c = (Cat) a;//ClassCastException

/*
    毕老师和毕姥爷的故事(不会被和谐)
*/

class 毕姥爷
{
    void 讲课()
    {
        System.out.println("管理");
    }
    void 钓鱼()
    {
        System.out.println("钓鱼");
    }
}

class 毕老师 extends 毕姥爷
{
    void 讲课()
    {
     System.out.println("Java");
    }
    void 看电影()
    {
        System.out.println("看电影");
    }
}


class Demo
{
    public static void main(String[] args)
    {
        
        毕姥爷 x = new 毕老师();
        x.讲课();//java
        x.钓鱼();
        毕老师 y = (毕老师)x;
        y.看电影();
    }
    
}

向上转型为了提升扩展性,限制子类的特有功能.

向下转型为了使用子类的特有功能.

abstract class Animal
{
    abstract void eat();
}

class Cat extends Animal
{
    void eat()
    {
        System.out.println("鱼");
    }
    void catchMouse()
    {
        System.out.println("抓老鼠");
    }
}

class Dog extends Animal
{
    void eat()
    {
        System.out.println("啃骨头");
    }
    void lookHome()
    {
        System.out.println("看家");
    }
}


class Demo
{
    public static void main(String[] args)
    {
        
         method(new Cat());
         method(new Dog());
    }

    public static void method(Animal a)
    {
        a.eat();
        //a instanceof Animal -->true
        if(a instanceof Cat) //instanceof:用于判断对象的具体
        {                    //类型,只能用于引用数据类型判断
            Cat c = (Cat)a;
            c.catchMouse();
        }
        else if(a instanceof Dog)
        {
            Dog d = (Dog)a;
            d.lookHome();
        }
    }
    
}

多态时成员的特点:

class Fu
{
    int num = 3;  //如果把这行注释,下面会报错.
    
}

class Zi extends Fu
{
    int num =4;
}

class Demo
{
    public static void main(String[] args)
    {
        Fu f = new Zi();
        System.out.println(f.num);//3 
    }
}
//变量不能覆盖,只有方法才会覆盖

1.成员变量:

  编译时:参考引用型变量所属的类中是否有调用的成员变量,有,编译通过,没有,编译失败.

  运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量.

      简单说:编译和运行都参考等号的左边(父类的).

 2.成员函数(非静态):

    

class Fu
{
    void show()
    {
        System.out.println("fu show");
    }
}

class Zi extends Fu
{
    void show()
    {
        System.out.println("zi show");
    }
}

class Demo
{
    public static void main(String[] args)
    {
        Fu f = new Zi();
        f.show();
    }
}

如果子类没有show()方法,才会去父类调用show();

编译时:参考引用型变量所属的类中是否有调用的函数,有,编译通过,没有,编译失败.

运行时:参考的是对象所属的类中是否有调用的函数.

简单说:编译看左边,运行看右边.

3.静态函数:

简单说:编译和运行都看左边.

静态函数放在方法区中,不会覆盖父类的方法,

直接去找父类的了.因为静态不涉及对象也可以直接用类名调用方法,

故静态其实可当做不考虑多态.

 

内部类:

把一个类定义在另一个类的里面(内置类,嵌套类);

/*
    内部类访问特点:
1.内部类可以直接访问外部类中的成员.
2.外部类要访问内部类,必须建立内部类的对象.
*/
class Outer
{
    private int num=3;
    class Inner //内部类
    {
        void show()
        {
            System.out.println("show run..."+num);
        }
    }

    public void method()
    {
        Inner in = new Inner();
        in.show();
    }
}

//直接访问外部类中的内部类中的成员.
Outer.Inner in = new Outer().new Inner();

 

一般用于类的设计,

分析事物时,发现该事物的描述中还有事物,而且这个事物还在访问被描述

事物的内容,这时就是还有的事物定义成内部类来描述.

如果内部类是静态的,相当于一个外部类

class Outer
{
    private static int num=3;
    static class Inner //内部类
    {
        void show()
        {
            System.out.println("show run..."+num);
        }
    }

    public void method()
    {
        Inner in = new Inner();
        in.show();
    }
}

class Demo
{
    public static void main(String[] args)
    {
        Outer.Inner in = new Outer.Inner();
        in.show();
    }
}

如果内部类是静态的,成员是静态的.

class Outer
{
    private static int num=3;
    static class Inner //内部类
    {
        void show()
        {
            System.out.println("show run..."+num);
        }
        static void function()//如果内部类中定义了静态成员,该内部类也必须是静态的
        {
            System.out.println("function run"+num);
        }
    }

    public void method()
    {
        Inner in = new Inner();
        in.show();
    }
}

class Demo
{
    public static void main(String[] args)
    {
        Outer.Inner.function();
    }
}

为什么内部类能直接访问外部类中的成员呢?

那是因为内部类持有了外部类的引用,外部类名.this.

class Outer
{
    int num =3;
    class Inner
    {
        int num=4;
        void show()
        {
            int num=5;
            System.out.println(Outer.this.num);
            //num-->4
            //this.num-->5;
            //Outer.this.num-->3;
        }
    }

    void method()
    {
        new Inner().show();
    }
}

class Demo
{
    public static void main(String[] args)
    {
        new Outer().method();
    }
}

内部类在局部位置上只能访问局部中被final修饰的局部变量.

(自己测试的可以访问,网上说1.8以后的新特性?)

/*
    内部类可以存放在局部位置上.
    内部类在局部位置上只能访问局部中被final修饰的
    局部变量.
*/
class Outer
{
    int num=3;
    Object method()
    {
        final int x= 11;
        class Inner
        {
            void show()
            {
                System.out.println("show..."+x);
            }
        }
        Object in = new Inner();
        
        return in;//0x0045
    }

}

class Demo
{
    public static void main(String[] args)
    {
        Outer out = new Outer()
        Object obj = out.method();
        //方法一出栈x就没了,
    }
}

匿名内部类:

就是内部类的简写格式.

必须有前提:

内部类必须继承或实现一个外部类或者接口.

匿名内部类:其实就是一个匿名子类对象.

格式:new 父类or接口(){子类内容}

abstract class Dm
{
    abstract void show();
}

class Outer
{
    int num=4;
    public void method()
    {
        new Dm()
        {
            void show()
            {
                System.out.println("show..."+num);
            }
            void haha()
            {

            }
        }.show();
    }
}




class Demo
{
    public static void main(String[] args)
    {
        new Outer().method();
    }
}

通常使用的场景之一:

当函数参数是接口类型时,而且接口中的方法不超过三个.可以用匿名内部类作为实际参数进行传递.

interface Inter
{
    void show1();
    void show2();
}

class Outer
{
    /*
    class Inner implements Inter
    {
        public void show1()
        {
        }
        public void show2()
        {
        }
    }
    public void method()
    {
        Inner in = new Inner();
        in.show1();
        in.show2();
    }*/
    public void method()
    {
        Inter in = new Inter()
        {
            public void show1()
            {
            }
            public void show2()
            {
            }
        };
        in.show1();
        in.show2();
    }
}



class Demo
{
    public static void main(String[] args)
    {
        new Outer().method();

        //show(new InterImpl());
        show(new Inter()
        {
            public void show1(){}
            public void show2(){}
        });
    }
    public static void show(Inter in)
    {
        in.show1();
        in.show2();
    }
}

/*
class InterImpl implements Inter
{

}
*/
class Outer
{
    void method()
    {
        Object obj = new Object()
        {
            public void show()
            {
                System.out.println("show run");
            }
        }
        obj.show();//出错
        //因为匿名函数类这个子类对象被向上转型为Object
        //这样就不能再使用子类的特有方法了
        //这其实是多态和匿名函数的结合.
    }
}
class Fu
{
    Fu()
    {
        show();
    }

    void show()
    {
        System.out.println("hehe");
    }
}

class Zi extends Fu
{
    int num = 9;
    Zi()
    {
        //super();
        //在这里进行显示初始化
        System.out.println("zi constructor..."+num);
    }
    void show()
    {
        System.out.println("show run"+num);
    }
}


class Demo
{

    public static void main(String[] args)
    {
        new Zi();
        //show run 0;
        //zi constructor 9
    }
    
}

 

posted on 2016-12-06 23:00  夜行锦衣  阅读(92)  评论(0编辑  收藏  举报

导航