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

java零基础入门学习第八天——相关笔记

程序员文章站 2022-07-10 08:21:22
...

多态

多态:多种状态,同一对象在不同情况下表现出不同的状态或行为

Java中实现多态的步骤:

1.要有继承(或实现)关系

2.要有方法重写

3.父类引用指向子类对象(is a关系)

package study3.demo;
//Animal类的子类
public class Dog extends Animal {
//因为狗吃骨头,所以优化父类的eat()方法
        @Override       //方法重写的关键字;有方法重写时建议写上
    public void eat() {
//            getName()通过这个调用父类的name,父类用private修饰了
            System.out.println(getName()+"吃骨头");
        }
}
package study3.demo;
//定义父类
public class Animal {
//    姓名
    private String name;
//空参
    public Animal() {
    }

    public Animal(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void eat() {
        System.out.println("吃东西");
    }
}
package study3.demo;
/*
    动物类案例:
        已知父类Animal,成员变量为:姓名,成员方法为:eat()方法
        其有一子类Dog类,请用该案例摸你多态
 */
public class Test4 {
    public static void main(String[] args) {
//需求“演示多态
       /*
            Java中实现多态的是哪个步骤:
                1.要有继承(或实现)关系
                2.要有方法重写
                3.要有父类引用指向子类对象
        */
//        多态:狗是一个动物
        Animal a = new Dog();       //父类引用指向子类对象
        
//        测试成员方法的调用
//        结论:多态中调用成员方法是
//        编译看左(左边的类型(父类:Animal)有没有这个成员)
//        运行看右(运行时具体用的是右边类(子类:Dog)中的该成员)
        a.setName("哈士奇");
//        
        a.eat();
    }
}

结论:多态中调用成员方法是
编译看左(左边的类型(父类)有没有这个成员)
运行看右(运行时具体用的是右边类(子类)中的该成员)

多态效果演示

需求:父类型变量作为参数时,可以接受任意子类对象

package study3.demo;

public class Dog2 extends Animal2 {
    @Override
    public void eat() {
        System.out.println(getName()+"吃骨头");
    }
}
package study3.demo;

public class Mouse extends Animal2 {
    @Override
    public void eat() {
        System.out.println(getName()+"吃奶酪");
    }
}
package study3.demo;
//Animal类父类
public class Animal2 {
    private String name;

    public Animal2() {
    }

    public Animal2(String name) {
        this.name = name;
    }
//因为成员变量时私有的,所以要有setXxx()和getXxx()方法
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

//    成员方法
    public void eat() {
        System.out.println("吃饭");
    }
}
package study3.demo;
/*
    已知父类Animal,成员变量为:姓名,成员方法为:eat()方法
    它有两个子类Dog类,Mouse类,两个子类都重写了Animal类中的eat()方法
    在测试类中,定义showAnimal()方法,用来测试Dog类和Mouse类
 */
public class Test5 {
    public static void main(String[] args) {
//用来测试Dog类和Mouse类
//        测试Dog类
        Dog2 d = new Dog2();
        d.setName("小A");
        showAnimal(d);

//        测试Mouse类
        Mouse m = new Mouse();
        m.setName("小B");
//        m.eat();
        showAnimal(m);
    }
    //        需求:在该类中定义showAnimal()方法
//    传统做法
//    因为是在测试类中的,所以要加static
//    public static void showAnimal(Dog2 d) {
//        d.eat();
//    }
//    public static void showAnimal(Mouse m) {
//        m.eat();
//    }
//    多态的做法
//    多态的使用场景:
//    父类型可以作为形参的数据类型,这样可以接受其任意的子类对象
    public static void showAnimal(Animal2 a) {
        a.eat();
    }
}

多态的使用场景:父类型可以作为形参的数据类型,这样可以接受其任意的子类对象

多态关系中成员变量的使用

需求:子父类中定义了同名的成员变量,如何调用

package study3.demo;

public class Animal3 {
    String name = "小A";

}
package study3.demo;

public class Dog3 extends Animal3 {
    String name = "小B";

}
package study3.demo;
/*
    结论:多态关系中,成员变量是不涉及到重写的
    简答记忆:多态关系中,使用成员变量,遵循“编译看左,运行看左”
            编译看左:在编译期间会看左边的类型有没有这个成员,没有就报错,有就不报错
            运行看左:在运行期间使用的是左边的类型中的这个成员
 */

public class Test6 {
    public static void main(String[] args) {
//        通过多态的方式创建对象,然后测试成员变量的使用
//        多态:父类引用指向子类对象
        Animal3 a = new Dog3();
        System.out.println(a.name);
//        通过普通方式创建对象,然后测试
        Dog3 d = new Dog3();
        System.out.println(d.name);
    }
}

结论:多态关系中,成员变量是不涉及到重写的(成员变量不能重写)
简答记忆:多态关系中,使用成员变量,遵循“编译看左,运行看左
编译看左:在编译期间会看左边的类型有没有这个成员,没有就报错,有就不报错
运行看左:在运行期间使用的是左边的类型中的这个成员

多态的好处:

**1.可维护性:**基于计划才能关系,只需要维护父类代码,提高了代码的复用性,大大降低了维护程序的工作量

**2.可扩展性:**把不同的子类对象都当做父类看待,屏蔽了不同子类对象间的差异,做出通用的代码,以适应不同的需求,实现了向后兼容

多态的缺点:

不能使用子类特有成员

类型转换:当需要使用子类特有功能时,需要进行类型转换

向上转型(自动类型转换):子类型转换成父类型

如:将Dog()类型的转成Animal类型的

Animal a = new Dog();

向下转型(强制类型转换):父类型转换成子类型

如:将Animal类型的animal转成Dog类型,小括号里面写要转成的类型

Dog d = (Dog) animal;

注意事项:

1.只能在继承层次内进行转换(ClassCastException)

2.将父类对象咋混换成子类对象之前,使用instanceof进行检查

package study3.demo;

public class Animal4 {
    public void eat() {
        System.out.println("吃饭");
    }
}
package study3.demo;

public class Dog4 extends Animal4 {
    public void eat() {
        System.out.println("狗吃骨头");
    }
//    狗类独有的方法,父类中是没有这个成员方法的
    public void whtch() {
        System.out.println("狗会看家");
    }
}
package study3.demo;
//子类,
public class Cat extends Animal4 {

}
package study3.demo;
/*
    需求:
    多态的好处:1.可维护性;2.可扩展性
    多态的弊端:父类引用不能使用子类的特有成员
    解决方案:通过“类型转换”实现
    注意:只能在继承层次内进行转换,否则会报ClassCastException异常
    将父类对象转换成子类之前,使用instanceof进行检查
    instanceof关键字的用法:
    对象名 instanceof 数据类型
    意思是判断前边的对象是否是后边的数据类型
 */
public class Test7 {
    public static void main(String[] args) {
//        需求:通过多态创建对象,调用子类中的成员
//        Animal4 a = new Animal4();
        Animal4 a = new Dog4();

//        调用eat()方法
        a.eat();

//        调用watch()方法,属于子类独有的方法
//        a.watch();      //报错
//        正确的写法
//        Dog4 d = (Dog4) a;
//        d.whtch();

//        不正常的转换            ClassCastException
//        Cat c =(Cat)a;
//            优化后的方法:判断当前对象是否Dog类的对象,如果是,再调用watch()方法
        if (a instanceof Dog4) {        //判断是否是Dog类的对象
//            能走到这里,说明条件满足
            Dog4 d = (Dog4)a;
            d.whtch();
        }
    }
}