扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
一直不太明白的一个关于继承方面的问题
例如: Dog 类 继承了 Animal类。
Animal dog = new Dog(); 和 Dog dog = new Dog();
这两种声明dog对象有什么区别?
这要是放在项目中就可以看出好处了,书上的例子不美! 继承就是可以用父类的引用来new一个子类的对象 这种用法是为了产生多态 当调用父类中的方法时,如果子类有覆盖这个方法的话,那么调用的就是子类的这个方法。 |
这要是放在项目中就可以看出好处了,书上的例子不美!继承就是可以用父类的引用来new一个子类的对象 这种用法是为了产生多态, 当调用父类中的方法时,如果子类有覆盖这个方法的话,那么调用的就是子类的这个方法。
子类继承后可以重写,也可以不重写,看需要决定。如果重写的话在实例中调用的是新写的方法. 如果不重写的话在实例中调用的是父类的方法。
在内存分配上没有区别,都是Dog对象,但是第一种写法Animal dog = new Dog(); dog只能调用父类Animal里的方法和属性,要想使用子类Dog里的有父类Animal里没有的方法就比须向下转型,也就是强制转换(Dog)dog一下。
第二种写法Dog dog = new Dog(); 就没有这个问题了。
狗继承了动物!
动物 = new 狗;
这里只能调用动物的属性方法,如果狗继承动物后重写了动物里的一些方法,那么就调用狗重写的那个方法.
但是不能调用狗的自己的方法,比如狗欺负猫这个方法,动物没有,只有狗有.
狗 = new 狗;
可以调用狗从动物继承过来的方法,还包括它自己的特性的方法
1.内存分配
Animal dog = new Dog(); 在堆区建立Dog对象,在栈区建立Animal引用,该引用指向Dog对象
Dog dog = new Dog(); 在堆区建立Dog对象,在栈区建立Dog引用,该引用指向Dog对象
2.使用
Animal dog = new Dog();可以使用未被重写的非privateAnimal方法,Animal上非private所有属性,以及在Dog中重写Animal的方法
Dog dog = new Dog(); 可以使用Dog ,Animal的非 private属性和方法
java中对象类型的变量可以指向自己的实例或它的任何子类的实例
Animal dog = new Dog(); // 父类的引用指向子类的事例,dog变量的类型是父类的,可以把Dog看成是Animal
他们的区别就不难理解 Animal的引用可以指向其他子类,而这样就可以用到JAVA的动态帮定,
把父类的引用作为参数可以自动识别子类的方法,这样就不必要去写每个子类的具体逻辑
Java code
public class Test {
public static void main(String[] args) {
Animal animal = new Dog("dog");
System.out.println(getAnimalInfo(animal));
animal = new Cat("Cat");
System.out.println(getAnimalInfo(animal));
}
public static String getAnimalInfo(Animal animal) {
return "This is " + animal.getName();
}
}
abstract class Animal {
public abstract String getName();
}
class Dog extends Animal{
private String name = "";
public Dog(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
class Cat extends Animal {
private String name = "";
public Cat(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
如果不用多态,那每个子类都要写自己的逻辑,但子类很多很复杂的时候,多态的优点就体现出来了
运行时多态的三原则
1.对象不变;(改变的是主观认识)
2.对于对象的调用只能限于编译时类型的方法,如调用运行时类型方法报错。
在上面的例子中:Animal a=new Dog();对象a的编译时类型为Animal,运行时类型为dog。
注意:编译时类型一定要为运行时类型的父类或者同类型。
对于语句:Dog d=(Dog)a。将d强制声明为a类型,此时d为Dog(),此时d就可以调用运行时类型。注意:a和d指向同一对象。
3.动态类型判定实际调用的方法。即它调用覆盖后的方法。
(1)Animal dog=new Dog(); (2)Dog dog=new Dog(); 第一个定义对象实现了多态,(1)和(2)中的调用方法其实是一样的,但是多态比较灵活 |
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者