一个关于java多态的问题

NickPac 2003-04-22 06:35:03
java对多态处理得很好,但是有时候不能达到我的要求。比如:
一个方法,如果参数类型是Father,那么我们可以传入一个Father实例,或者它的一个子类实例,做不同的操作。
现在我想传入一个子类的实例,但是想完成传父类实例所作的操作,应该怎么样做?
下面是一个例子,将打印出:
I am Father
I am Son
如何能打印出
I am Father
I am Father(还是传入一个子类的实例)

//Father.java
public class Father{
public void draw(){
System.out.println("I am Father");
}
}

//Son.java
public class Son extends Father{
public void draw(){
System.out.println("I am Son");
}
}

//MainTest.java
public class MainTest{
public void test(Father a){
a.draw();
}
public static void main(String[] args){
Father father=new father();
Son son=new Son();
MainTest m=new MainTest();
m.test(father);
m.test(son);
}
}

有人说java的late binding机制从根本上限制了java不能完成这样的需要,是么?
...全文
32 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
muymuy 2003-04-25
  • 打赏
  • 举报
回复

楼上的仁兄,对于多态,重载,覆盖的概念,我想你还不是很理解。
有必要澄清一下,

多态是指,对象在调用某个方法(假设为:void methodA())的时候,是根据对象的类类型来做判断,如果这个类中有methodA()方法,并且要有同样的参数和返回值,那么它就调用这个方法,如果没有methodA()方法,那么就到它的直接父类取找,如果还是没有,在往上找,直到找到为止,肯定是能找到的,如果找不到的话,编译都通不过。

覆盖,子类重写父类的方法,所谓重写,那么,方法名、返回值和参数都要相同才叫重写。

重载,方法名相同,返回值相同,但是参数不同。

因此多态是依靠覆盖来实现的。

在你的程序中,是方法名相同,返回值相同,但参数不同,只能算是重载,根本没有覆盖一说,所以多态就谈不上了。

你可以看看这篇文章,
http://www.c-view.org/journal/004/cpp_critique.htm
wyqiang 2003-04-23
  • 打赏
  • 举报
回复
http://expert.csdn.net/Expert/topic/1660/1660081.xml?temp=.6399805
我做的作业
会有用的
muymuy 2003-04-23
  • 打赏
  • 举报
回复

superlee的做法很巧妙,但是不能达到需要的效果,同时也没有用到多态,用到了方法名重载,Son里的draw(Son son)重载了Father的draw(Father father)。这样一来,Son里就有了两个方法,
一个是继承自父类的draw(Father father),另外一个是自己的draw(Son son);
在调用draw的时候,会根据输入参数的类型来做判断,如果输入参数类型是Son 型,
就调用draw(Son son);如果是Father 类型和Father 的其他子类,那么就调用draw(Father father)。

对于 NickPac (悠悠) 提出的要求,其实还有一个很简单的方法,既然在Son中想调用Father的draw方法,那么,在Son中就不overwrite父类的draw方法:
//Father.java
public class Father{
public void draw(){
System.out.println("I am Father");
}
}

//Son.java
public class Son extends Father{
}

//MainTest.java
public class MainTest{
public void test(Father a){
a.draw();
}
public static void main(String[] args){
Father father=new father();
Son son=new Son();
MainTest m=new MainTest();
m.test(father);
m.test(son);
}
}
superLee 2003-04-23
  • 打赏
  • 举报
回复
笔误:
“3、”中:“而对于向下转型要严格的多”,应当是宽松的多。
superLee 2003-04-23
  • 打赏
  • 举报
回复
1、我有没有用到多态:
通俗的解释多态性:
多态性:“同名”但“不同的功能实现形式”(即在基类中提供一种方法的实现,但可以在子类对
该方法加以重写并给出自己的实现但要求保持功能的实现形式相同)。
重载是多态的一种实现形式,所以在我的代码里面用到了多态!这一点可以说是勿庸置疑的!
2、为什么只出现一种结果,请看一下下面的代码:
//MainTest.java
public class MainTest{
public void test(Son a){
a.draw(a);
}
public static void main(String[] args){
Father father=new Father();
Son son=new Son();
MainTest m=new MainTest();
//m.test(father);
m.test(son);
}
}
3、为什么java里面需要加入参数的形式才能打印出I am Father而“MainTest中写m.test
((Father)son)毫无用处,仍然打印I am Son”
是这样,java里面对于向上转型有很严格的规定,必须用显式的方法来进行。
而对于向下转型要严格的多,我在函数里加入参数,正是为了让它显式的转型。
对于java的转型记得有这样一个比喻:
父母<相当于父类>可以随便干预子女的事情<转型到子类>,
而子女是不可以随便干预父母的事情的<转型到父类>,
但如果你提出申请<显式的方法转型>,还是可以通融一下。
最后提一下:java的转型<cast>与C++是不一样的!
CyberH 2003-04-22
  • 打赏
  • 举报
回复
我觉得superLee(superLee)的方法不能算是多态,因为这样一来就只有一种结果
NickPac 2003-04-22
  • 打赏
  • 举报
回复
多谢superLee和muymuy以及回复的朋友。superLee的解决办法并不是我希望的答案,我希望只修改子类的代码,就可作出不同的操作,比如muymuy所给的c++代码中使用
Father::draw()或者cout<<"I am son"<<endl中一个,就可以完成两种效果。在java中可行么?按照superLee给的代码,在不改动父类的情况下是要永远打印I am Father了对么?也就是说,我希望可以在子类中自由选择override or not.
但是superLee给出的方法很巧妙,能不能给我解释一下为什么加入参数就可以强制类型转换呢?而如果我在MainTest中写m.test((Father)son)毫无用处,仍然打印I am Son
kangta 2003-04-22
  • 打赏
  • 举报
回复
你好象并没有调用的son类的draw方法哦!
UP的UP superLee(superLee)你的方法a.draw(a);这里哪个a是public void test(Father a)传递的a啊?
superLee 2003-04-22
  • 打赏
  • 举报
回复
解释一下:
我在你的draw函数中加入一个参数,使draw具备“型别检查的能力”。
你在调用MainTest的test函数时,由于Test要求的是Father型,
son此时被强制转型为Father型了。这样,调用就是Father的draw。
hslinux 2003-04-22
  • 打赏
  • 举报
回复
也不太动,学习ing。
muymuy 2003-04-22
  • 打赏
  • 举报
回复

我不知道什么是late binding机制,但是,这在java里是绝对做不到的。
但是在C++里可以做到:

//Father.h
#ifndef _FATHER__
#define _FATHER__
#include <iostream>
using namespace std;

class Father{
public:
virtual void draw(){
cout<<"I am Father"<<endl;
};
};
#endif //_FATHER__

//Son.h
#ifndef _SON__
#define _SON__
#include "Father.h"

class Son : public Father{
public:
virtual void draw(){
Father::draw();
//cout<<"I am son"<<endl;
};
};
#endif //_SON__

//main.cpp
#include "Son.h"
#include "Father.h"

void test(Father * param)
{
param->draw();
}

void main()
{
Father *father=new Father();
Son *son=new Son();
test(father);
test(son);
}

//运行结果为:
I am Father
I am Father
CyberH 2003-04-22
  • 打赏
  • 举报
回复
对呀,java的机制不可能完成这样的需要,多态性本来就是为了使客户端用这样的方式以不变应万变~~~~
superLee 2003-04-22
  • 打赏
  • 举报
回复
"I am Father(还是传入一个子类的实例)"
实际上需要向上转型,需要强制转换!
我跟你改写后的程序:<try it!>
//Father.java
public class Father{
public void draw(Father Iam){
System.out.println("I am Father");
}
}
//Son.java
public class Son extends Father{
public void draw(Son Iam){
System.out.println("I am Son");
}
}
//MainTest.java
public class MainTest{
public void test(Father a){
a.draw(a);
}
public static void main(String[] args){
Father father=new Father();
Son son=new Son();
MainTest m=new MainTest();
m.test(father);
m.test(son);
}
}

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧