今天我们老师给我们讲了多态问题,其中关于父类引用指向子类对象.始终不知道是怎么回事,
如THREAD类中的构造函数public Thread(Runnable target)我们老师就说有父类引用指向子类对象,但我看了很久也想不明白,各位能否告诉我哪个是父类引用,哪个是子类对象.以及多态在这个函数里是如何实现的?
如THREAD类中的构造函数public Thread(Runnable target)我们老师就说有父类引用指向子类对象,但我看了很久也想不明白,各位能否告诉我哪个是父类引用,哪个是子类对象.以及多态在这个函数里是如何实现的?
对象之间的关系,在功能上可能存在正交性,而我们要尽量地把这种正交性体现出来,于是我们就要重新界定对象的粒度。我们借用Java的Thread类,和Runnable接口作为例子的原型,记住,只是以其为原型,我所讲述的并非是Java的线程。
class Thread
{
void start(Runnable run)
}interface Runnable
{
void run();
}
我再次请大家注意的是,我的Thread类并没用实现Runnable类,因为我认为那并不必要,事实上,我们也不鼓励Java的开发人员派生Thread,而是鼓励他们实现Runnable接口。
(new Thread(new Runnable() {
public void run() {}})).start();
这样的使用方式(除了代码风格外),才是我们鼓励的。但是由于我们只讲必要性,而不涉及到具体使用的方便性,所以我的Thread类没有实现Runnable接口。
那么我们思考线程对象和Runnable实现类的真实含义,一个线程对象,也许维护了OS的线程内核对象(可能是模拟的,比如Ruby的Fake Thread)。但是线程对象本身可以加载什么方法,或者说在一个线程上做什么事情,那是Runnable实现类要如何描述的问题,这两个对象有着关系,但是在功能上确实正交的。于是,我们把它们分成两个对象的粒度。
到此,如果我们有一个Timer类,或者一个叫做Fiber的类。我们只是想把我们要做的事情加载到Timer事件中,或者是Fiber纤程上,我们就会更好地意识到Runnable接口和Thread类的正交性。
直接来看看用法,可能要好理解一些。你说的Thread类中的那构造方法public Thread(Runnable target),你可以看到参数是一个Runnable类型的。我们一般是这样使用的:先定义一个类,并继承Runnable接口class Test implements Runnable{public void run() {
...
}}
然后,我们可以利用下面的一行代码来启动线程:
new Thread(this).start();这里的this就是实现了Runnable接口的类对象。相当于是把一个父类的引用指向了那个新new出来的Thread对象,只不过,该对象没有一个承载变量
//例:
class Animals
{
public Animals()
{
}
public void call()
{
}
}
// 则狗,猫,,可以看作是其子类 例: class dog extends Animals
{
public dog()
{
}
public void call()
{
System.out.println("汪汪");
}
} class cat extends Animals
{
public cat()
{
}
public void call()
{
System.out.println("喵喵");
}
} public class Test
{
public static void main(String args[])
{
Animals A = new dog();
A.call();
A = new cat();
A.call();
}
}
编译运行下,就知道了
}
class B extends A{
}
A a=new B();
父类引用指的是a 子类对象指的new B() new出来的那个对象
父类引用指向子类对象 这个说法只是语言表达上的问题 不是你不懂 而是你没分清什么叫父类引用 什么叫指向String x="abc" abc是个实在的对象 x只是个引用 就好像abc是间房子 x只是个门牌号 你要通过x才能找到那个abc
x就代表了那个abc 这就叫x指向abc 在实际需要abc的地方 只要用x代替就可了再简单解释下多态的问题
A a=new B();
或者
B b=new B();
A a=b;因为B继承自A 所以B具备A的基本特征 你把B里比A多出来的东西砍掉 它就是A 所以可以a=b; 但是这个时候并没有把b里多余的东西砍掉 只是让a与b引用同一个对象 在需要的时候可以把b截成A类型 也可以把a还原成B类型
但是你不能让b指向一个A类型的对象 因为A类型无法转换成B类型 我想这样你应该能大概了解什么叫"父类引用指向子类对象"了同是新手 有错误的地方请高手指正
Thread parent = currentThread();this.daemon = parent.isDaemon();
this.priority = parent.getPriority();
this.contextClassLoader = parent.contextClassLoader;
...看到这几行你估计应该能明白了吧,不过真正要理解线程,还是甘草兄那个境界比较高,呵呵,我还要继续努力学习啊!
因为括号里的参数传递进来的肯定是Runnable的子类