Read Sean
Read me, read Sean.
posts - 508, comments - 655, trackbacks - 9, articles - 4
導航
BlogJava
首頁
新隨筆
聯系
聚合
管理
公告
關于我
人生是一場對話
我的譯作
聲明
所有文章和代碼在這里以"現狀"提供,作者不提供任何形式的擔保,也沒有授予除閱讀和有條件共享之外的任何權利。除非特別說明,所有文章均為本blog作者原創,如需轉載請注明出處和原作者,如用于商業目的,需作者本人書面許可。
推薦文章
Pylons起步
常用鏈接
我的隨筆
我的評論
我的參與
最新評論
留言簿
(29)
給我留言
查看公開留言
查看私人留言
隨筆分類
(842)
Computer Usage(72)
Database(9)
GNU/Linux(30)
On Eclipse(52)
On Java(131)
On Python(11)
Operating Systems(70)
Other Languages(28)
Programming in General(41)
Project Management(25)
Reading(189)
The Other Side(129)
Web Clips(55)
隨筆檔案
(507)
2014年5月 (1)
2014年4月 (1)
2014年3月 (1)
2014年1月 (1)
2012年11月 (1)
2011年8月 (2)
2011年7月 (1)
2011年3月 (1)
2011年2月 (2)
2011年1月 (5)
2010年12月 (2)
2010年1月 (1)
2009年12月 (1)
2009年11月 (1)
2009年10月 (1)
2009年9月 (1)
2009年8月 (1)
2009年7月 (1)
2009年6月 (2)
2009年5月 (1)
2009年4月 (1)
2009年3月 (2)
2009年2月 (2)
2009年1月 (15)
2008年12月 (10)
2008年11月 (1)
2008年10月 (4)
2008年9月 (1)
2008年8月 (3)
2008年7月 (3)
2008年6月 (2)
2008年5月 (2)
2008年4月 (1)
2008年3月 (4)
2008年2月 (5)
2008年1月 (4)
2007年12月 (2)
2007年11月 (2)
2007年10月 (1)
2007年9月 (1)
2007年8月 (2)
2007年7月 (2)
2007年6月 (4)
2007年5月 (3)
2007年4月 (5)
2007年3月 (4)
2007年2月 (23)
2007年1月 (26)
2006年12月 (30)
2006年11月 (14)
2006年10月 (6)
2006年9月 (2)
2006年8月 (3)
2006年7月 (3)
2006年6月 (5)
2006年5月 (3)
2006年4月 (17)
2006年3月 (9)
2006年2月 (28)
2006年1月 (17)
2005年12月 (8)
2005年11月 (23)
2005年10月 (43)
2005年9月 (19)
2005年8月 (30)
2005年7月 (13)
2005年6月 (7)
2005年5月 (5)
2005年4月 (12)
2005年3月 (20)
2005年2月 (19)
2005年1月 (8)
文章檔案
(4)
2010年12月 (1)
2009年1月 (1)
2005年8月 (1)
2005年1月 (1)
Friends' blogs
emu in blogjava
jackei
kukoo's blog
搜索
積分與排名
積分 - 780018
排名 - 55
最新評論
1.?re: [Tips] <abbr>: 一個有趣的HTML標簽
dqwdqwdqw
--額范圍啊
2.?re: [Tips] <abbr>: 一個有趣的HTML標簽
<scrtpt>alert("fwefwargvaerg");</script>
--額范圍啊
3.?re: iText vs FOP - Java動態生成PDF的兩個選擇
用0.95報錯的大概意思是還不支持。。。。。
本地字庫的字體embet不進去。。。。
--fop
4.?re: iText vs FOP - Java動態生成PDF的兩個選擇
代碼拷貝運行報錯啊
--fop
5.?11[未登錄]
404
--00
6.?re: [Tips] Spring 2.5.6新特性之packagesToScan
101
--11
7.?re: Mac安裝tsocks
評論內容較長,點擊標題查看
--mzj
8.?re: [Jakarta Commons筆記] org.apache.commons.lang.time
哈哈,什么情況,10年前的文章,今天來讀一讀
--宇飛
9.?re: Mac安裝tsocks
有一個proxychains-ng項目,還在更新,可以試試的
--ayanamist
10.?re: SourceForge.net上的文件下載頁面無法打開的一種解決方法
評論內容較長,點擊標題查看
--Douglas
11.?re: [Tips] Windows/Linux雙系統重裝Windows后無法進入Linux的最速解決辦法
linux是進去了,windows又進不去了
--ss
12.?re: [RPi] 樹梅派安裝Archlinux和藍牙
這種便宜dongle有個問題就是藍牙MAC地址是一樣的,同一環境下使用多個會有點麻煩,需要找個辦法繞過去。
--laogao
13.?re: [愚公移山] 團隊CVS資源庫從CVSNT遷移到Linux
評論內容較長,點擊標題查看
--guest
14.?re: [Jakarta 筆記] org.apache.commons.lang.math[未登錄]
評論內容較長,點擊標題查看
--doctor
15.?re: Jakarta Commons專題 - 隨筆列表
可惜晚了這么多年,才讀到樓主的文章。
--rox
閱讀排行榜
1.?[Tips] 惱人的winmail.dat及解決辦法(36618)
2.?[Eclipse筆記]在Eclipse下做UML設計(28393)
3.?[Tips] Spring 2.5.6新特性之packagesToScan(22725)
4.?iText vs FOP - Java動態生成PDF的兩個選擇(13758)
5.?IntelliJ IDEA 常用快捷鍵(12887)
6.?pyPdf - 用Python方便的處理PDF文檔(12650)
7.?[Linux起步]配置Java和Eclipse環境(9862)
8.?Java命令行實用工具jps和jstat(9488)
9.?你真的理解了繼承和多態嗎?(7671)
10.?Drip, Transfusion, Perfusion還是Infusion?關于一個詞的翻譯(7552)
11.?[Eclipse筆記]配置SWT開發環境(7530)
12.?[Jakarta Commons筆記] org.apache.commons.lang.time(7357)
13.?如何在Ubuntu下訪問本地NTFS分區(6496)
14.?[Jakarta Commons筆記] org.apache.commons.lang.builder(6083)
15.?J2SE(TM) 5.0專題 之 語言特性 // 勘誤信息請直接回復(5738)
評論排行榜
1.?[Tips] 惱人的winmail.dat及解決辦法(48)
2.?6個Gmail邀請,需要的朋友請在這里回復。(已結束)(34)
3.?[Eclipse筆記]在Eclipse下做UML設計(29)
4.?[Eclipse筆記]請對Java、Sun、NetBeans、Eclipse感興趣朋友的看看Eclipse對Sun的心態吧(19)
5.?令人驚喜的Feisty,讓人失望的Evolution(15)
6.?你真的理解了繼承和多態嗎?(14)
7.?[Jakarta Commons筆記] org.apache.commons.lang.time(11)
8.?iText vs FOP - Java動態生成PDF的兩個選擇(11)
9.?[Eclipse筆記]SWT真正的優勢不是快這么簡單(9)
10.?[Linux起步]SuSE Linux 10.0正式發布(9)
11.?Drip, Transfusion, Perfusion還是Infusion?關于一個詞的翻譯(8)
12.?[Tips] 在Ubuntu Linux 6.06 LTS (Dapper Drake)上安裝CVS服務(8)
13.?Nikon F80 + AF Nikkor 50mm/1.4 D 的魅力(8)
14.?[Linux起步]配置Java和Eclipse環境(7)
15.?J2SE(TM) 5.0專題 之 語言特性 // 勘誤信息請直接回復(7)
你真的理解了繼承和多態嗎?
Posted on 2005-06-07 15:18
laogao
閱讀(7671)
評論(14)
編輯
收藏
所屬分類:
On Java
、
Programming in General
最近被同事問起一道SCJP的題目,是跟繼承和多態有關的。具體的題目我就不重復了,來看一段我自己敲的代碼:
1
package sean.work.test;
2
3
public
class
DoYouReallyUnderstandPolymorphism
{
4
5
public
static
void
main(String[] args)
{
6
A a
=
new
A();
7
B b
=
new
B();
8
a.s
=
"
[AA]
"
;
9
b.s
=
"
[BB]
"
;
10
System.
out
.println(a.s);
//
prints "[AA]"
11
System.
out
.println(b.s);
//
prints "[BB]"
12
System.
out
.println(a.getS());
//
prints "[AA]"
13
System.
out
.println(b.getS());
//
prints "[BB]"
14
System.
out
.println(
"
====================
"
);
15
a
=
b;
//
a now refers to object b
16
System.
out
.println(a.s);
//
prints "[A]" <<--1-- the class A copy
17
System.
out
.println(b.s);
//
prints "[BB]"
18
System.
out
.println(a.getS());
//
prints "[BB]"
19
System.
out
.println(b.getS());
//
prints "[BB]"
20
System.
out
.println(
"
====================
"
);
21
((A)b).s
=
"
[AA]
"
;
//
<<--2-- changes the class A copy in object b
22
System.
out
.println(a.s);
//
prints "[AA]" <<--3-- class A copy changed
23
System.
out
.println(b.s);
//
prints "[BB]"
24
System.
out
.println(a.getS());
//
prints "[BB]"
25
System.
out
.println(b.getS());
//
prints "[BB]"
26
}
27
28
}
29
30
class
A
{
31
String s
=
"
[A]
"
;
32
String getS()
{
33
return
s;
34
}
35
}
36
37
class
B extends A
{
38
String s
=
"
[B]
"
;
39
String getS()
{
40
return
s;
41
}
42
}
43
這里我們的B類繼承自A類,重寫了getS()方法,于是我們可以利用到多態。如果你留意15、16、21、22這幾行的話,你也許就會知道我在說什么了。假如你覺得這樣的打印結果是理所當然,那么我想你可以完全忽略這篇隨筆,因為我要講的就集中在這幾行,而你已經很清楚的理解背后的含義。
下面跟感興趣的朋友們說說我的理解:
直觀的講,我們很容易輕信當"a = b;"以后,變量a指向的對象是B類的b那個對象,自然a.s就應該等同于b.s,然而事實并非如此。當B繼承A時,父類A的字段s并沒有被B的字段s取代,而是保留了一份拷貝,所謂重寫(Override),那是對方法而言的。于是,當我們new B()時,在實際創建的對象中,包含了兩個版本的字段s,一個"[A]"(屬于A類)一個"[B]"(屬于B類)。而方法getS()只有一個版本。這就是在繼承過程中字段和方法的區別。也就是說,重寫的概念和字段無關。在第16行,我們通過a.s訪問的是b這個對象中保留的A類的字段s;而在21行,我們改變的正是這個A類版本的s字段。
多態的精髓在于動態確定對象的行為,而對象的行為體現在方法而非字段,字段代表的更多的是對象的狀態。于是只有方法的多態而沒有字段的多態。從上面的代碼可以看出,不管你用什么類型的變量存放對象b的引用,最終調用的方法版本都是b的真實類型那個版本,這就是多態的威力。
從編譯的角度來看,上面代碼中的s字段和getS()方法的不同在于:s字段是在編譯期靜態鏈接(你可以改變它的值,但是它在對象中的相對地址已經確定好),而getS()方法是在運行期動態鏈接的。
說了這么多,真的不知道我表達清楚沒有,畢竟沒有系統研究過OO和編譯原理,說得不當的地方還請多多包涵。最后,請不要學我這里的編碼風格,因為很顯然應該對main方法中的代碼段執行Extract Method重構了,我這里只是為了注釋方便。
// BTW,時不時抽空想想這樣的問題感覺真不錯。
Feedback
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2005-06-07 16:26 by
小毅
謝謝您,學到很容易忽略的東西,覺得很重要
再謝謝你...
#
原來字段和方法有這樣的區別哦
回復
更多評論
2005-06-08 09:02 by
emu
>>只有方法的多態而沒有字段的多態
以前都沒有想過這個問題哦。
前兩天遇到一個內嵌類的方法重載時候的古怪問題,不知是否與此有關,正好回頭去研究一下。
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2005-06-08 12:16 by
FS
Java的對象模型偶不太清楚,不過通過對Delphi的對象模型的了解,我感覺應該和Java沒有太大的區別。
按照樓主所說的,當執行了語句“a=b”后,變量a和b的內容應該是不變的,所變的是a指向的對象實體中的指向類的指針的內容,在Delphi中,這個指針叫做vptr,CPP中也是如此叫法。vptr直接指到類的VMT(不知道Java中如何叫法);因此,再次使用a.s訪問實例變量,則要進入b指向的對象實體中進行字段的查找,但由于b里面存在兩個s字段,并且以類型信息為區分方式,所以找到的是類型A的字段s。至于編譯處理方面,我想應該是把類型信息作為字段的前綴或者后綴。
同樣,當執行了“((A)b).s=“[AA]””后,由于已經把b的類型轉化為A類型,而且b指針的未改變,所以在b的對象實體中,實際改變的是屬于類型A的字段s的內容。個人感覺,其實樓主已經說出了,對b中不同類型的同名字段的訪問方式。
最后留下一個問題:這種對象模型中的字段處理方式如果在繼承字段訪問量小的情況下是很浪費空間的。那么,這樣處理的優點又是什么?
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2005-06-08 12:18 by
FS
按照OO這種東西在語言設計上的考慮,對象所涉及到的所有內容就是三塊:對象指針,對象實體和對象所屬類型的內存布局。而對象實體中只存放狀態信息,即對象所屬類型的實例字段的內容,因此,從這個角度考慮,多態和實例字段的信息是沒有任何關系的。但對于類字段,即申明為static的字段就未必了。
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2005-07-20 23:24 by
丑男
System.out.println(a.s); // prints "[A]"
這句確實我沒想到!看來真被難倒了
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2006-05-15 17:30 by
songxu
非常感謝
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2006-07-15 17:22 by
tcpipok
我是想到了,不過就像樓主所說的,這種編碼風格不好,子類盡量不要用父類用過的變量名,真的是容易搞混,這種代碼用來考試可以,但用來編程不好.
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2006-08-17 20:34 by
小小
請問:
java中字符串的連接是不是一種多態的表現?
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2007-03-05 22:52 by
谷鈺
@tcpipok
我不知道你是否理解OO真正的精髓,以上用法展示了面向對象設計的核心思想,通過虛方法調用,實現不同子類對同一行為(方法)的不同實現。希望以下例子可以給大家一些啟發:
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2007-03-05 23:05 by
谷鈺
public class Employee {
protected String name = "張三";
private double salary = 1000;
public Employee(String name, double salary) {
this.name = name;
this.salary = salary;
}
public Employee() {
this("王老五", 1);
}
public String getDetails() {
return "姓名:" + this.name + ", 工資: " + this.salary;
}
public double getSalary() {
return this.salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o instanceof Employee) {
Employee te = (Employee) o;
return this.salary == te.getSalary() && this.name.equals(te.getName());
}
return false;
}
public int hashCode() {
if (this.name == null) {
return 0;
}
return this.name.hashCode();
}
public String toString() {
return "$$" + this.getDetails();
// return super.toString();
}
public static void printAll(Employee[] all) {
System.out.println("所有員工:");
for (int i = 0; i < all.length; ++i) {
System.out.println(all[i].getDetails());
}
}
public static void main(String[] args) {
Employee e = new Employee("張三", 2500);
System.out.println(e.getDetails());
Manager m = new Manager("李四", 4500, "軟件開發部");
System.out.println(m.getDetails());
Employee ee = new Manager("王五", 4500, "軟件銷售部");
System.out.println(ee.getDetails());
if (ee instanceof Manager) {
Manager mmm = (Manager) ee;
System.out.println(mmm.getDepartment());
}
Employee e2 = new Employee("張三", 2500);
System.out.println(e.equals(e2));
System.out.println(e);
System.out.println("##" + e);
Employee[] eAll = {
e, m, ee
};
printAll(eAll);
}
}
class Manager extends Employee {
private String department = "44";
public Manager() {
super();
this.department = "計算機";
}
public Manager(String name, double salary, String department) {
super(name, salary);
this.department = department;
}
public String getDetails() {
return super.getDetails() + ", 管理部門: " + this.department;
}
public String getDepartment() {
return this.department;
}
}
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2007-03-05 23:11 by
谷鈺
核心在
public static void printAll(Employee[] all) {
System.out.println("所有員工:");
for (int i = 0; i < all.length; ++i) {
System.out.println(all[i].getDetails());
}
}
函數的設計上,通過Employee隱藏所有雇員子類的細節,通過getDetails()方法來隱藏不同雇員(Manger,Engineer等)對詳細信息的函數細節。
只有這樣的函數才能最大程度上復用,既當設計有新的Employee子類定義也不許要對此函數做任何的修改,個人認為面向對象的最大好處是提高程序的復用性,降低維護成本。這些需要多態,繼承才能作到。:)
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2007-03-06 09:38 by
大胃
謝謝 谷鈺 的回復!
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2008-05-21 17:06 by
tonytang
to 谷鈺,你的代碼也沒有回答tcpipok的疑問啊。子類和父類定義相同的屬性有意義嗎?
#
re: 你真的理解了繼承和多態嗎?
回復
更多評論
2008-06-25 11:00 by
shell
寫的太好了。
學習了很多。
新用戶注冊
刷新評論列表
只有注冊用戶
登錄
后才能發表評論。
網站導航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
相關文章:
IntelliJ IDEA 常用快捷鍵
[Tips] Windows環境下Apache最基本的調優方法
"上海"是如何變成"涓婃搗"的?
如何讓統一版本的Eclipse RCP應用同時支持多個平臺
Java命令行實用工具jps和jstat
用Scala解Hanoi塔
[Tips] Spring+Hibernate之“暴力”update
[Tips] Spring 2.5.6新特性之packagesToScan
easyb - Getting Started
Spring 3.0前瞻
Powered by:
BlogJava
Copyright © laogao
主站蜘蛛池模板:
亚洲免费观看视频
|
国产在线19禁免费观看
|
亚洲国产精品成人精品无码区
|
思思久久99热免费精品6
|
国产做床爱无遮挡免费视频
|
国产精品亚洲综合一区在线观看
|
亚洲成AV人片在WWW
|
精品国产免费一区二区
|
精品国产亚洲第一区二区三区
|
国产不卡免费视频
|
免费看又黄又爽又猛的视频软件
|
亚洲人成影院在线无码观看
|
久久久久女教师免费一区
|
亚洲国产精品无码中文字
|
91久久精品国产免费一区
|
91嫩草亚洲精品
|
精品剧情v国产在免费线观看
|
亚洲AV综合色区无码一二三区
|
国产免费人视频在线观看免费
|
一个人看的免费视频www在线高清动漫
|
亚洲精品456播放
|
久久国产精品萌白酱免费
|
亚洲免费视频播放
|
国产一级一片免费播放
|
任你躁在线精品免费
|
亚洲欧洲日本国产
|
日本黄色免费观看
|
a级午夜毛片免费一区二区
|
亚洲欧洲日产国码二区首页
|
国产男女性潮高清免费网站
|
在线观看免费视频一区
|
亚洲天堂2016
|
亚洲欧洲国产精品香蕉网
|
久草视频免费在线
|
一级毛片免费播放男男
|
亚洲乱码日产精品BD在线观看
|
四虎永久免费地址在线网站
|
久久久久国产精品免费免费不卡
|
亚洲精品无码专区
|
亚洲国产女人aaa毛片在线
|
日本a级片免费看
|