欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

多态,内部类

程序员文章站 2022-04-15 23:42:17
一。接口作为方法参数, 接口作为返回值:具体使用的都是接口的实现类对象1.创建接口public interface Interface1 { void method1(); void method2();}2.创建实现类public class InterfaceImpl implements Interface1{ @Override public void method1() { System.out.println("实现类重写方法1");...

一。接口作为方法参数, 接口作为返回值:
具体使用的都是接口的实现类对象

1.创建接口
public interface Interface1 {
    void method1();
    void method2();
}
2.创建实现类
public class InterfaceImpl implements  Interface1{
    @Override
    public void method1() {
        System.out.println("实现类重写方法1");
    }

    @Override
    public void method2() {
        System.out.println("实现类重写方法2");
    }
}
3. 接口类型作为方法参数,返回值为接口类型
public class DemoIt {
    //接口类型返回值的方法
    public Interface1 it(Interface1 a){
        //此处等于默认有 Interface a=new InterfaceImpl();
        // a 调用的是哪个方法, 具体看传入的对象是哪个实现类
        a.method1();
        a.method2();
        System.out.println("结束");
        /*相当于创建了一个接口的实现类对象, 向上造型为接口类型
        Interface a=new InterfaceImpl();
        接口类型的对象返回return a;*/
        return a;//等于return new InterfaceImpl();
    }
}
4.主函数调用

public class Main {
    public static void main(String [] ages){
        DemoIt demo=new DemoIt();
        //接口无法创造对象,所以用实现类创造对象
        InterfaceImpl a=new InterfaceImpl();
        //实现类对象作为参数给It方法中的接口类型参数做参数
        demo.it(a);

        InterfaceImpl a2=new InterfaceImpl();
        //调用方法并且接收返回值时,由于 xx.it(xx)返回值是Interface类型
        Interface1 re=demo.it(a2);
    }
}

二。多态

1.父类
public class Fu {
    int age = 10;
    int num = 100;

    public void m1() {
        System.out.println("Fu m1方法");
    }

    public void m2() {
        System.out.println("Fu m2方法");
    }

    public int getAge() {
        return this.age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
2.子类
public class Zi extends Fu {
    // 和父类中同名的成员变量
    int age = 20;
    // 和父类中不同的成员变量 - 子类自己单独声明的
    int score = 150;
    // 额外继承了父类中的num变量

    // 重写父类中的m1方法
    public void m1() {
        System.out.println("Zi m1方法");
    }
    // 继承了父类的m2方法

    // 子类自己的方法 m3
    public void m3() {
        System.out.println("Zi m3方法");
    }

    @Override
    public int getAge() {
        return age;
    }

}
3.父类型引用 指向 子类型对象
 Fu f = new Zi();
 // 无关类 不叫 向上造型, 写法错误
//        Fu f1 = new Self();
/*
以下两种不叫多态
        Fu f1 = new Fu();
        Zi zi = new Zi();
*/
4.多态表现方面1: 
    成员变量的调用, 子父类中拥有相同的成员变量并且都有一对get/set方法
    如果通过引用直接调用成员变量 f.age, 看引用变量f左边类型来调用
    通过方法调用成员变量f.getAge(), 看引用变量右边类型来调用
    public class Main1 {
    public static void main(String[] args) {
        Fu f = new Zi();
        System.out.println(f.age); // 10

        // 子类中重写了getAge()方法, 得到20
        // 子类中没有重写getAge()方法, 得到10
        System.out.println(f.getAge()); // 20

        System.out.println(f.num);
        // Fu类中没有声明score变量, 不能直接调用
//        System.out.println(f.score);
        // int a = (int)3.14;   double d = 3;
        // 向下转换类型
        Zi zi = (Zi) f;
        System.out.println(zi.score);

    }
}
5. 多态的表现方面2: 成员方法的调用
 最终调用的是哪个方法:优先调用子类重写过的,子类中如果没有重写, 
 就调用父类的方法
 public class Main2 {
    public static void main(String[] args) {
        Fu f = new Zi();
        f.m1();
        // m3没有在Fu中声明, 所以不能直接调用
//        f.m3();
        // 如果想用子类自己的方法, 需要强制转换
        Zi zi = (Zi) f;
        zi.m3();
    }
}

②多态: Animal a1 = new Cat();
Animal a2 = new Dog();

1.抽象父类,抽象方法
public abstract  class Animal {
    
    public  abstract void eat();
}
2.子类
  public class Cat extends Animal {
     @Override
     public void eat() {
         System.out.println("吃鱼");
     }
     public void catchMouse(){
         System.out.println("抓老鼠");
     }
 }
 public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("吃骨头");
    }
    public void watchHouse(){
        System.out.println("看门");
    }
}
3。多态主要用处是Animal作为参数,可以传递多种类型的对象,以Animal抽象类为返回值的那个方法可以返回多种不同种类的对象
public class Test {
    public static void main(String [] ages){
        //向上造型:父类型引用指向子类型对象
        Animal m1=new Cat();
       // m1.eat();
        Animal m2=new Dog();
       // m2.eat();
       /*
        Cat c=new Cat();
        Dog d=new Dog();
        c.catchMouse();
        d.watchHouse();
        */
        //showCatEat(c);
        //showDogEat(d);
        showAnimalEat(m1);
        showAnimalEat(m2);
    }
    public static Animal salepet(){//以Animal抽象类为返回值,这个方法可以返回多种不同
        return null;
    }
      //Animal作为参数,可以传递多种类型的对象
    public static void showAnimalEat(Animal a){
        if(a instanceof Cat){//instanceof用来判断a是否是new出的Cat
            Cat cat=(Cat) a;
            cat.catchMouse();
        }
        else if( a instanceof Dog){
            Dog dog=(Dog) a;//向下转型
            dog.watchHouse();
        }
        a.eat();
    }
}

三。内部类: 类中写个类
种类: 成员内部类,静态内部类,局部内部类[匿名内部类]
1.成员内部类:权限 public,protected,(default),private
使用:
内部类中, 可以随意使用外部类成员
外部类中, 使用内部类成员时需要创建内部类对象
无关类中, 使用内部类成员
1.间接调用, 在外部类方法中调用内部类方法
main方法中, 调用外部类方法
2.直接调用, 需要创建内部类对象
外部类.内部类 a = new 外部类().new 内部类();
内部类和外部类有同名成员变量
外部类的成员变量: 外部类.this.变量
内部类的成员变量: this.变量

// 外部类
public class Body {
    public void walk() {
        System.out.println("身体在行走");
        // 外部类中, 直接创建内部类对象
        Heart heart = new Heart();
        heart.beat();
        // 外部类中使用内部类成员变量, 需要内部类对象
        System.out.println(heart.num);
        System.out.println(a); // 外部类的a
    }
    private int a = 10;
    // 成员内部类: 成分和外部类一样
    public class Heart {
        int num;
        int a = 20;
        public void beat() {
            int a = 30;
            // 内部类中可以直接使用外部类成员
            System.out.println("心脏跳动" + a++);
            // 内部类的成员a
            System.out.println(this.a);
            // 外部类的成员变量a
            System.out.println(Body.this.a);
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // 在无关类中 使用Body的内部类Heart
        Body body = new Body();
        // 间接调用内部类
        body.walk();

        // 直接调用内部类, 通过外部类对象创建内部类对象
        Body.Heart heart = body.new Heart();//与//Body.Heart heart = new Body().new Heart();相同
        heart.beat();
    }
}

2.局部变量a:
局部内部类中使用局部内部变量必须为final

public class Outer {
    private int b = 20;
    public void m1() {
        // 和局部内部类同方法的局部变量 a
        /*final */int a = 10;
        class Inner {
            public void innerM1() {
                int c = 0;
                System.out.println("局部内部类m1" + a);
                System.out.println("成员变量: " + b);
            }
        }
        Inner i = new Inner();
        i.innerM1();
      //a ++; final 不可变
        b ++;
    }

}

3.局部内部类: 在方法内部定义类, 只在方法中有效
在局部内部类中, 使用局部变量, 必须是final的
JDK8 后, 局部变量事实上没有发生改变, 那么final可以省略
一次性的类, 只能用一次
不能使用权限修饰符
局部内部类, 需要类只使用一次, 优化 -> 匿名内部类

public interface MyInterfaceA {
    void methodAbs1();
    void methodAbs2();
}

// 只想用一次, 只想在Outer类中的m1方法中使用
public class MyInterfaceImpl implements MyInterfaceA {
    @Override
    public void methodAbs1() {
        System.out.println("方法1");
    }

    @Override
    public void methodAbs2() {
        System.out.println("方法2");
    }
}

public class Outer {
    public void m1() {
        class InnerImpl implements MyInterfaceA {
            @Override
            public void methodAbs1() {
                System.out.println("内部类实现1");
            }
            @Override
            public void methodAbs2() {
                System.out.println("内部类实现2");
            }
        }

        // 使用接口的方法, 创建接口的实现类
        InnerImpl impl = new InnerImpl();
        impl.methodAbs1();
        impl.methodAbs2();
    }
}

4.匿名内部类: 继承抽象类或实现接口
语法: new 接口/抽象类() {
int a;
// 实现的所有抽象方法
}
匿名内部类, 只能用一次, new一个对象
匿名对象, 只能使用一次, 只能调用一次方法
注意: 匿名内部类 和 匿名对象 不是一回事 ! ! !

public interface MyInterfaceA {
    void methodAbs1();
    void methodAbs2();
}

public class Outer {
    public static void main(String[] args) {
        // 匿名内部类本质: 实现接口或者继承抽象类
        /*
            new MyInterfaceA(){..}
            new: 创建MyInterfaceA 的实现类对象
            MyInterfaceA: 想要实现的接口, 抽象类
            {..}: 真正的类, 没有名字
            弊端: 只能用一次, 只能创建一次对象
         */
         MyInterfaceA impl = new MyInterfaceA() {
             int a = 10;
            @Override
            public void methodAbs1() {
                System.out.println("内部类实现1" + a++);
            }
            @Override
            public void methodAbs2() {
                System.out.println("内部类实现2");
            }
        };
        impl.methodAbs1();
        impl.methodAbs2();

        new MyInterfaceA() {
            int a = 10;
            @Override
            public void methodAbs1() {
                System.out.println("内部类实现1" + a++);
            }
            @Override
            public void methodAbs2() {
                System.out.println("内部类实现2");
            }
        }.methodAbs1();
        // 匿名对象, 只能调用一次方法
        new Outer().getClass();
        new Outer().hashCode();
    }
}
  1. 静态内部类: 对比 成员内部类 => 静态方法 和 成员方法
public class Outer {

    // 成员方法
    public void m1() {
        new Inner();
        new InnerField();
    }
    // 静态方法
    public static void m2() {
        new Inner();
//        new InnerField();
    }
    // 成员内部类
    public class InnerField {

    }
    // 外部类的成员变量
    int a = 10;
    // 外部类的静态成员变量
    static int b = 20;
    // 静态内部类, 属于类的
    public static class Inner {
        public void m3() {
            // 不能使用非静态成员
//            System.out.println(a);
            System.out.println(b);
        }
    }
}

import com.zzxx.demo8.Outer.Inner;

public class Main {
    public static void main(String[] args) {
        // 成员内部类创建对象, 需要外部类对象
        Outer.InnerField inner1 = new Outer().new InnerField();

        // 静态内部类创建对象
        Outer.Inner inner2 = new Outer.Inner();

        // 简化 -> 需要import
        Inner inner3 = new Outer.Inner();

    }
}

本文地址:https://blog.csdn.net/LDRaaa/article/details/107370083