你對於本章知識的學習總結
1.1 嘗試使用思惟導圖總結有關繼承的知識點。
參考資料:html
1.2 使用常規方法總結其餘上課內容。app
(1)瞭解了類型轉換(cast),只能在繼承層次內進行類型轉換,將父類強制轉換成子類以前,應使用instanceof進行檢查。
(2)懂得如何運用控制可見性的4個訪問修飾符:
private -- 僅對本類可見
public -- 對全部類可見
protected -- 對本包和全部子類可見
默認 -- 沒有標明任何修飾符,通常不用,對本包可見
(3)區分覆蓋(Override)與重載(Overload)的區別。ide
Q1.註釋的應用
使用類的註釋與方法的註釋爲前面編寫的類與方法進行註釋,並在Eclipse中查看。(截圖)函數
對圖形面積、周長求和的實驗代碼作了簡單的註釋
類的註釋
工具
方法的註釋
學習
Q2.面向對象設計(大做業1,很是重要)
2.1 將在網上商城購物或者在班級博客進行學習這一過程,描述成一個故事。(不得少於50字,參考QQ羣中PPT的範例)
1.進入網上購物商城網站
測試
2.進入登陸頁面,登入帳號
flex
3.查找所要購買的商品,並在相應界面進行選擇
網站
4.進入對應商品查看商品屬性,加入購物車
5.查看購物車進行確認
6.結算購買商品
2.2 經過這個故事咱們能發現誰在用這個系統,系統中包含的類及其屬性方法,類與類之間的關係。嘗試找到這些類與屬性,並使用思惟導圖描述類、屬性、方法及類與類之間的關係。
參考資料:**
UML類圖
面向對象案例-借款者姓名地址.zip
Q3.ManagerTest.zip代碼分析
分析ManagerTest.zip中的代碼,回答幾個問題:
3.1 在本例中哪裏體現了使用繼承實現代碼複用?回答時要具體到哪一個方法、哪一個屬性。
class Manager extends Employee //Manager類繼承父類Employee類,得到父類的屬性和方法 { /** * @param n the employee's name * @param s the salary * @param year the hire year * @param month the hire month * @param day the hire day */ public Manager(String n, double s, int year, int month, int day) { super(n, s, year, month, day);//調用父類的有參構造函數來完成對子類的初始化 bonus = 0; } public double getSalary() { double baseSalary = super.getSalary();//調用父類的getSalary()方法 return baseSalary + bonus; } public void setBonus(double b) { bonus = b; } private double bonus; }
如上代碼註釋上所述,Manager類繼承父類Employee類,得到父類的屬性和方法,父類屬性中的name,salary,hireday則無需從新定義,還利用關鍵字super調用了Employee類的構造函數對子類的對象進行初始化,以及調用了getSalary()方法。
3.2Employee
類及其子類Manager
都有getSalary方法,那怎麼區分這兩個方法呢?
若是父類和子類都有相同的方法名,可使用super關鍵字調用父類的方法,使用super能夠訪問父類被子類隱藏的同名的成員。super.getSalary()使用的是父類中的方法,而getSalary()則是子類的方法。
3.3 文件第26行e.getSalary()
,究竟是調用Manager類的getSalary方法仍是Employee類的getSalary方法。
運行代碼獲得的結果如上圖所示,源代碼中
Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15);
staff[0]=boss的屬性是Manager類的,因此調用的是Manager類中getSalary()方法,在Manager的getSalary()中繼承了它的父類Employee的getSalary()方法;staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15);
staff]1]和staff[2]的屬性是Employee類的,因此調用的是Employee類中的getSalary方法。
3.4 Manager
類的構造函數使用super調用父類的構造函數實現了代碼複用,你以爲這樣的有什麼好處?爲何不把父類構造函數中的相關代碼複製粘貼到Manager的構造函數中,這樣看起來不是更直觀嗎?
雖然在每一個類中複製相關的代碼看起來很直觀,可是代碼量很是大,同時給代碼的維護上也會帶來極大的不便,例如代碼中的name,salary,hireday要進行修改,就要在每個類中進行修改,這樣豈不是費時費力。若是使用了繼承的思想來實現代碼,用super調用父類的構造函數,在修改時只需在父類上進行相應的修改,這樣大大方便了代碼的維護,而且減小了代碼的冗餘度,提升了代碼的複用性,使代碼看起來更加簡潔,何樂而不爲呢。
Q4.Object類
4.1 編寫一個Fruit類及屬性String name,如沒有extends自任何類。使用System.out.println(new Fruit());是調用Fruit的什麼方法呢?該方法的代碼是從哪來的?嘗試分析這些代碼實現了什麼功能?
class Fruit{ private String name; } public class Main { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(new Fruit()); } }
運行結果以下:
object的toString()方法通常就是打印某個對象的「地址」,即對象的所屬類以及該對象的哈希值
參考文章
在Java中,全部的對象都是繼承自Object,天然繼承了toString方法,在當使用System,out.println()裏面爲一個對象的引用時,自動調用toString方法講對象打印出來。若是重寫了tostring方法則調用重寫的toString 方法。
查看println
的源代碼便可知道toString方法的來源
4.2 若是爲Fruit類添加了toString()方法,那麼使用System.out.println(new Fruit());調用了新增的toString方法。那麼其父類中的toString方法的代碼就沒有了嗎?若是同時想要複用其父類的toString方法,要怎麼操做?(使用代碼演示)
·調用新增的toString方法
class Fruit{ private String name; @Override public String toString() { return "Fruit [name=" + name + "]"; } //新增的toString方法 } public class Main { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(new Fruit()); } }
運行結果:
·父類Object中的toString方法固然還在,只需用關鍵字super調用便可。
class Fruit{ private String name; @Override public String toString() { return "Fruit [name=" + name + "]"+"\n"+super.toString(); } //新增的toString方法 } public class Main { public static void main(String[] args) { // TODO Auto-generated method stub System.out.println(new Fruit()); } }
運行結果以下:
4.3 Fruit類還繼承了Object類的eqauls方法。嘗試分析其功能?本身編寫一個equals方法覆蓋父類的相應方法,功能爲當兩個Fruit對象name相同時(忽略大小寫),那麼返回true。(使用代碼證實你本身覆蓋的eqauls方法是正確的)
equals()是對兩個對象的地址值進行的比較(即比較引用是否相同),相同返回true,不一樣返回false。
Object類的eqauls方法,查看源代碼以下圖
本身編寫equals方法覆蓋父類,能夠利用自動生成,只需對忽略大小寫上進行修改便可,代碼以下:
package Q4; class Fruit{ private String name; public Fruit(String name){ this.name=name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Fruit other = (Fruit) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equalsIgnoreCase(other.name)) //java.lang.String.equalsIgnoreCase()方法比較字符串到另外一個字符串,忽略大小寫因素。 return false; return true; } } public class Main { public static void main(String[] args) { // TODO Auto-generated method stub //System.out.println(new Fruit()); Fruit a=new Fruit("Apple"); Fruit b=new Fruit("apple"); System.out.println(a.equals(b)); } }
運行結果以下:
4.4 在4.3的基礎上使用ArrayList
import java.util.ArrayList; class Fruit{ private String name; public Fruit(String name){ this.name=name; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Fruit other = (Fruit) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equalsIgnoreCase(other.name)) //java.lang.String.equalsIgnoreCase()方法比較字符串到另外一個字符串,忽略大小寫因素。 return false; return true; } @Override public String toString() { return "Fruit [name=" + name + "]"; } } public class Main { public static void main(String[] args) { // TODO Auto-generated method stub //System.out.println(new Fruit()); Fruit a=new Fruit("apple"); Fruit b=new Fruit("Apple"); Fruit c=new Fruit("banana"); ArrayList<Fruit> fruitList=new ArrayList<Fruit>(); fruitList.add(b); if(!fruitList.contains(a)){ fruitList.add(a); } if(!fruitList.contains(c)){ fruitList.add(c); } System.out.println(fruitList); } }
運行結果以下:
ArrayList的contatins方法,從頭至尾檢索字符串,含有字符串的子串就返回true,不然返回false,能夠查看源代碼,以下圖
Q5.代碼閱讀:PersonTest.java(abstract、多態)
5.1 畫出類的繼承關係
5.2 讀懂main函數,將本身推測的出代碼運行結果與真正運行結果進行比較。嘗試分析緣由
運行結果以下:
Person類是一個抽象類,沒有實例對象,Student類,Employee類,Manager類和Programmer類的toString()方法是利用super關鍵字調用父類Person類的toString()方法,得出運行結果,Manager類和Programmer類是繼承Employee類的,Employee類是繼承Person類的。
5.3 子類中裏面使用了super構造函數,做用是什麼?若是將子類中的super構造函數去掉,行不行?
做用:調用父類的構造函數。
不能去掉,去掉後編譯器會調用父類無參構造函數,而PersonTest.java中沒有無參構造函數,會出現編譯出錯的問題。
5.4 PersonTest.java中的代碼哪裏體現了多態?你以爲多態有什麼好處?多態和繼承有什麼關係嗎?
參考文件:PersonTest.java
多態性:相同的形態,不一樣的行爲(不一樣的定義)
相同的方法名,不一樣的實現
父類類型變量能夠引用子類對象
多態的好處:
多態的好處:
1)可替換性(substitutability):多態對已存在代碼具備可替換性。例如,多態對圓Circle類工做,對其餘任何圓形幾何體,如圓環,也一樣工做。
2)可擴充性(extensibility):多態對代碼具備可擴充性。增長新的子類不影響已存在類的多態性、繼承性,以及其餘特性的運行和操做。實際上新加子類更容易得到多態功能。例如,在實現了圓錐、半圓錐以及半球體的多態基礎上,很容易增添球體類的多態性。
3)接口性(interface-ability):多 態是超類經過方法簽名,向子類提供了一個共同接口,由子類來完善或者覆蓋它而實現的。如圖8.3 所示。圖中超類Shape規定了兩個實現多態的接口方法,computeArea()以及computeVolume()。子類,如Circle和 Sphere爲了實現多態,完善或者覆蓋這兩個接口方法。
4)靈活性(flexibility):它在應用中體現了靈活多樣的操做,提升了使用效率。
5)簡化性(simplicity):多態簡化對應用軟件的代碼編寫和修改過程,尤爲在處理大量對象的運算和操做時,這個特色尤其突出和重要。
參考文章
多態和繼承的關係:
繼承:子類繼承父類中因此的屬性和方法,可是對於private的屬相和方法,因爲這個是父類的隱私,因此子類雖然是繼承了,可是沒有能夠訪問這些屬性和方法的引用,因此至關於沒有繼承到。
多態:就是父類引用能夠持有子類對象。這時候只能調用父類中的方法,而子類中特有方法是沒法訪問的,由於這個時候(編譯時)你把他看做父類對象的緣由,可是到了運行的時候,編譯器就會發現這個父類引用中原來是一個子類的對像,因此若是父類和子類中有相同的方法時,調用的會是子類中的方法,而不是父類的。
在碼雲的項目中,依次選擇「統計-Commits歷史-設置時間段」,而後搜索並截圖,以下圖所示
實驗碰到的問題、思考、收穫與解決方案
實驗第四題實際上是對第三題的稍加改造,利用繼承和多態的方法減小代碼的冗餘度,還用了抽象類,運用了abstract關鍵字。 實驗第五題主要是利用工具欄中的Source自動生成函數,遇到的問題是equals()函數的編寫。 實驗第六題更加熟練地使用super複用Person類的相關有參構造函數,利用Collections.sort()來進行排序。主要遇到的問題仍是equals()函數沒有考慮周全,以及ArrayList的運用。