我相信很多人学习面向对象时遇到过这样的问题,或者也可能是我自己比较极端的问题,就是父类(抽象父类)被子类继承时(Java里是单继承多实现),当我们去new一个子类对象这个父类到底有没有被实列化,如果没有被实列化为什么可以去调用抽象父类的成员属性和普通的成员方法。
声明一个抽象父类
/**
* Created by liming.qiao on 2017/7/5.
*/
public abstract class Animal {
public String name;
public Animal(){};
public Animal(String name) {
this.name = name;
}
public void run(){
System.out.println("父类普通方法被调用。。。");
}
abstract void shout();
}
声明一个子类继承父类实现他的抽象方法
/**
* Created by liming.qiao on 2017/7/5.
*/
public class Dog extends Animal {
int furColour;
public Dog(String name, int furColour) {
super(name);
this.furColour = furColour;
}
public void play(){
System.out.print("狗玩球。。。");
}
@Override
void shout() {
System.out.println("狗叫。。。。");
}
}
test——main方法
/**
* Created by liming.qiao on 2017/7/5.
*/
public class Test {
public static void main(String[] args){
Dog d = new Dog("smallfei",1);
d.shout();
d.run();
System.out.println(d.name);
}
}
控制台打印
狗叫。。。。
父类普通方法被调用。。。
smallfei
这种情况个人认为应该这么去理解,就是当你去实列化子类对象的时候,调用子类构造器,这里是先去调用父类的构造器去初始化父类, 但不是实列化父类 调用构造器不一定就是实列化,个人认为这时子类在内存中有了父类的内存结构在堆内存中只有子类一个对像只不过他的内存结构加载了父类的内存结构,那么又有人要问:当我是父类的引用指向子类对象我也可以掉用父类的普通成员方法,其实这时你父类引用指向的是子类对象,所以当然能调用父类的普通方法,但是java里子类的新增属性(成员属性和方法)对父类的引用是不可见的。如
/**
* Created by liming.qiao on 2017/7/5.
*/
public class Test {
public static void main(String[] args){
Animal animal=new Dog("bigpink",2);
animal.play();//是不可见的
System.out.print(animal.furColour);//是不可见的
}
}
控制台
Error:(7, 15) java: 找不到符号
符号: 方法 play()
位置: 类型为Animal的变量 animal
Error:(8, 32) java: 找不到符号
符号: 变量 furColour
位置: 类型为Animal的变量 animal
这个时候又有问题了,那为什么父类引用可以调用shout()方法,这就是Java面向对象里面核心的核心多态机制(dynamic binding),
1、发生了继承(Dog继承了Animal抽象类)
2、父类引用指向子类对象(animal这个引用指向Dog对像)
3、方法被重写(shout()方法被Dog重写)
只有这样才能发生多态,这样animal引用就可以掉子类重写过后的方法也一定是掉子类里面重写的shout()方法;多态内存图
其实我只是想写抽象类到底有没有被创建对象的,顺便把多肽也写了,有错误希望大家给指出互相学习~