201871010111-劉佳華《面向對象程序設計(java)》第6-7周學習總結java
實驗六 繼承定義與使用編程
實驗時間 2019-9-29數組
第一部分:理論部分。安全
1.繼承:已有類來構建新類的一種機制。檔定義了一個新類繼承另外一個類時,這個新類就繼承了這個類的方法和域,同時在新類中添加新的方法和域以適應新的狀況。ide
繼承的特色:具備層次結構;子類繼承了超類的方法和域。函數
2.類繼承的格式:class 新類名 extends 已有類名工具
已有類稱爲:超類(superclass)、基類(base class) 或父類(parent class)學習
新類稱做:子類(subclass)、派生類(derived class)或孩子類(child class)測試
1)繼承類中,子類的構造器不能直接訪問超類的私有域,必須調用超類構造器,且必須是第一條語句。ui
2)子類不能直接訪問超類的私有域,必須和其餘方法同樣使用公有接口。
3)子類中能夠增長域、增長方法或覆蓋(override)超類的方法,可是毫不能刪除超類的任何域和方法。
注:java不支持多繼承。
3.多態性:泛指在程序中同一個符號在不一樣狀況下具備不一樣解釋。
超類方法在子類中能夠重寫。
java中,對象變量是多態的。
繼承層次結構中,每一個子類對象也可視做超類對象,所以,也能夠將子類對象賦給超類變量。如:boss.setBouns(5000);
4:final類:不容許繼承的類,在類的定義中用final修飾符加以說明。
5:強制轉換類型:若是要把一個超類對象賦給一個子類對象變量,就必須進行強制類型轉換,格式以下:Manager boss=(Manager)staff【0】;
6.抽象類:abstract class Person
1)abstract方法不能被實例化,即只能聲明,不能實現!
2)包含一個或多個抽象方法的類自己必須被聲明爲抽象類。
7:Object類:全部類的超類。
8:equals方法:用於測試某個對象是否和另外一個對象相等。若是兩個對象有相同的引用,則他們必定相等。
9:hasCode方法:導出某個對象的散列碼(任意整數)。
兩個相等對象的散列碼相等。
10:toString方法:返回一個表明該對象域值的字符串。
格式:類名【域值】
11:枚舉類:它包括一個關鍵字enum,一個新枚舉類型的名字 Grade以及爲Grade定義的一組值,這裏的值既非整型,亦非字符型。
1)枚舉類是一個類,它的隱含超類是java.lang.Enum。
2)枚舉值並非整數或其它類型,是被聲明的枚舉類的自身實例
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
繼承創建了類與類的關係,同時也是多態特徵的前提。
java只支持單繼承,不支持多繼承(避免兩個父類出現同名方法的調用選擇困難)
「is-a」關係是繼承的一個明顯特徵。
2)多態:在程序中同一符號在不一樣狀況下有不一樣解釋。
在Java中,子類數組的引用能夠轉換成超類數組的引用,而不須要採用強制類型轉換。
3)final類和方法:final類不容許被繼承(不能作父類)
String類是一個final類的例子(故該類不能被擴展)
父類能夠直接引用子類,而子類不能直接父類(必須進行強制轉換類型),。咋進行強制轉換類型前,先檢查是否可以成功轉換,使用instanceof操做符實現。
super主要有兩種用法:
第一種用法主要用來在子類中調用父類的同名成員變量或者方法;第二種主要用在子類的構造器中顯示地調用父類的構造器,要注意的是,若是是用在子類構造器中,則必須是子類構造器的第一個語句。
4)抽象類:一個類必定被定義成抽象類,他就是一個專職父類。不能實例化,即不能建立對象,只能產生子類。
5)受保護訪問:若是但願超類的某些方法或域被子類訪問,就需在給超類定義時,將這些方法或域聲明爲protected。
Java中用於控制可見性的4個訪問修飾符:
1.僅對本類可見:private
2.對全部類可見:public
3.對本包和全部子類可見:protected
4.對本包可見:默認,不須要修飾符。
2.object類:全部類的超類。
1)equals方法:檢測一個對象是否等於另一個對象。若是兩個對象具備相同的引用,那麼他們必定相等。
2)equals方法具備如下特性:
自反性、對稱性、傳遞性、一致性
3.hashCode方法(散列碼):由對象導出的一個整型值。
散列碼能夠是任意整數。兩個相等的對象要求返回相等的散列碼。
4.枚舉類:比較兩個枚舉類型值是,不用equals,直接用「==」。全部枚舉類都是Enum類的子類。其中toString方法可以返回枚舉常量名。
每一個枚舉類都有一個靜態values方法,它將返回一個包含所有枚舉值的數組。
第二部分 :實驗部分
1、實驗目的與要求
(1) 理解繼承的定義;
(2) 掌握子類的定義要求
(3) 掌握多態性的概念及用法;
(4) 掌握抽象類的定義及用途。
2、實驗內容和步驟
實驗1: 導入第5章示例程序,測試並進行代碼註釋。
測試程序1:
1.在elipse IDE中編輯、調試、運行程序5-1 —5-3(教材152頁-153頁) ;
2. 掌握子類的定義及用法;
3. 結合程序運行結果,理解並總結OO風格程序構造特色,理解Employee和Manager類的關係子類的用途,並在代碼中添加註釋;
實驗5-1代碼以下:
ManagerTest:
package inheritance; /** * This program demonstrates inheritance. * @version 1.21 2004-02-21 * @author Cay Horstmann */ public class ManagerTest { public static void main(String[] args) { var boss = new Manager("Carl Cracker", 80000, 1987, 12, 15);//構建管理者對象 boss.setBonus(5000); var staff = new Employee[3]; //用管理者和僱員對象填充工做人員數組 staff[0] = boss; staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1); staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15); //遍歷打印全部員工對象的信息 for (Employee e : staff) System.out.println("name=" + e.getName() + ",salary=" + e.getSalary()); } }
Manager類:
//package inheritance; public class Manager extends Employee//繼承於Employee的子類 { private double bonus; /** * @param name the employee's name * @param salary the salary * @param year the hire year * @param month the hire month * @param day the hire day */ public Manager(String name, double salary, int year, int month, int day)//Manager構造器 { super(name, salary, year, month, day);//調用父類構造器 bonus = 0; } public double getSalary()//對於Salary的get方法 { double baseSalary = super.getSalary();//基本工資由父類getSalary得到 return baseSalary + bonus; } public void setBonus(double b) { bonus = b; } }
Employee類:
//package inheritance; import java.time.*; public class Employee { private String name; private double salary; private LocalDate hireDay; public Employee(String name, double salary, int year, int month, int day) { this.name = name; this.salary = salary; hireDay = LocalDate.of(year, month, day); } public String getName() { return name; } public double getSalary() { return salary; } public LocalDate getHireDay() { return hireDay; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } }
運行結果以下:
測試程序2:
1. 編輯、編譯、調試運行教材PersonTest程序(教材163頁-165頁);
2.掌握超類的定義及其使用要求;
3. 掌握利用超類擴展子類的要求;
4.在程序中相關代碼處添加新知識的註釋;
5. 刪除程序中Person類、PersonTest類,背錄刪除類的程序代碼,在代碼錄入中理解抽象類與子類的關係和使用特色。
實驗5-2代碼以下:
PersonTest:
//package abstractClasses; /** * This program demonstrates abstract classes. * @version 1.01 2004-02-21 * @author Cay Horstmann */ public class PersonTest { public static void main(String[] args) { var people = new Person[2]; //用Student和Employee對象填充人員數組 people[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1); people[1] = new Student("Maria Morris", "computer science"); // 打印全部Person對象的名稱和描述 for (Person p : people) System.out.println(p.getName() + ", " + p.getDescription()); } }
person類:
//package abstractClasses; public abstract class Person//定義抽象類型Person { public abstract String getDescription();//定義抽象描述 private String name; public Person(String name) { this.name = name; } public String getName() { return name; } }
Employee類:
//package abstractClasses; import java.time.*; public class Employee extends Person//子類Employee繼承父類Person { private double salary; private LocalDate hireDay; public Employee(String name, double salary, int year, int month, int day) { super(name);//繼承父類的方法 this.salary = salary; hireDay = LocalDate.of(year, month, day);//hireDay使用LocalDate的方法 } public double getSalary() { return salary; } public LocalDate getHireDay() { return hireDay; } public String getDescription() { return String.format("an employee with a salary of $%.2f", salary); } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } }
Student類:
//package abstractClasses; public class Student extends Person//子類Student繼承父類Person { private String major; /** * @param name the student's name * @param major the student's major */ public Student(String name, String major) { // pass name to superclass constructor super(name);// 將name傳遞給父類構造函數 this.major = major; } public String getDescription() { return "a student majoring in " + major; } }
運行結果以下:
刪除後override的代碼以下:
//package abstractClasses; import java.time.*; public class Employee extends Person { public Employee(String name, int i, int j, int k, int l) { super(name); // TODO Auto-generated constructor stub } @Override public String getDescription() { // TODO Auto-generated method stub return null; } @Override public String getName() { // TODO Auto-generated method stub return super.getName(); } private double salary; private LocalDate hireDay; /*public Employee(String name, double salary, int year, int month, int day) { super(name); this.salary = salary; hireDay = LocalDate.of(year, month, day); } public double getSalary() { return salary; } public LocalDate getHireDay() { return hireDay; } public String getDescription() { return String.format("an employee with a salary of $%.2f", salary); } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; }*/ }
a)abstract方法只能聲明,不能實現
b)包含一個或多個抽象方法的類自己必須被聲明爲抽象類
c)抽象方法充當着佔位的角色,它們的具體實如今子類中
d)抽象類不能被實例化,即不能建立對象,只能產生子類。
測試程序3:
1.編輯、編譯、調試運行教材程序5-八、5-九、5-10,結合程序運行結果理解程序(教材174頁-177頁);
2.掌握Object類的定義及用法;
3.在程序中相關代碼處添加新知識的註釋。
5-8示例程序:
Employee:
//package equals; import java.time.*; import java.util.Objects; public class Employee { private String name; private double salary; private LocalDate hireDay; public Employee(String name, double salary, int year, int month, int day) { this.name = name; this.salary = salary; hireDay = LocalDate.of(year, month, day); } public String getName() { return name; } public double getSalary() { return salary; } public LocalDate getHireDay() { return hireDay; } public void raiseSalary(double byPercent) { double raise = salary * byPercent / 100; salary += raise; } public boolean equals(Object otherObject) //Objects類中的equals方法用於檢測一個對象是否等於另一個對象 { // a quick test to see if the objects are identical if (this == otherObject) return true; // must return false if the explicit parameter is null if (otherObject == null) return false; //若是顯示參數爲空,則返回false // if the classes don't match, they can't be equal if (getClass() != otherObject.getClass()) return false; //若是不是相同類型的對象,則返回false,getClass方法將返回一個對象所屬的類 // now we know otherObject is a non-null Employee var other = (Employee) otherObject; // test whether the fields have identical values return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay); } public int hashCode() { return Objects.hash(name, salary, hireDay); /*Objects.hash() 這個類用於操做對象的靜態實用方法這些工具包括用於計算對象的哈希代碼的空安全或空容錯方法,返回一個對象的字符串,並比較兩個對象 Object類中的hashCode方法導出某個對象的散列碼。散列碼世人以整數,表示對象的存儲地址 兩個相等對象的散列碼相等*/ } public String toString() //方法返回一個表明該對象域值的字符串 //toString { return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay=" + hireDay + "]"; } }
Manager:
package equals; public class Manager extends Employee//子類Manager繼承父類Employee { private double bonus; public Manager(String name, double salary, int year, int month, int day) { super(name, salary, year, month, day); bonus = 0; } public double getSalary() { double baseSalary = super.getSalary(); return baseSalary + bonus; } public void setBonus(double bonus) { this.bonus = bonus; } public boolean equals(Object otherObject) { if (!super.equals(otherObject)) return false; Manager other = (Manager) otherObject; // super.equals檢查這個和其餘屬於同一個類 return bonus == other.bonus; } public int hashCode() { return java.util.Objects.hash(super.hashCode(), bonus); } public String toString() { return super.toString() + "[bonus=" + bonus + "]"; } }
EqualsTest:
package equals; /** * This program demonstrates the equals method. * @version 1.12 2012-01-26 * @author Cay Horstmann */ public class EqualsTest { public static void main(String[] args) { Employee alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15); Employee alice2 = alice1; Employee alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15); Employee bob = new Employee("Bob Brandson", 50000, 1989, 10, 1); System.out.println("alice1 == alice2: " + (alice1 == alice2)); System.out.println("alice1 == alice3: " + (alice1 == alice3)); System.out.println("alice1.equals(alice3): " + alice1.equals(alice3)); System.out.println("alice1.equals(bob): " + alice1.equals(bob)); System.out.println("bob.toString(): " + bob); Manager carl = new Manager("Carl Cracker", 80000, 1987, 12, 15); Manager boss = new Manager("Carl Cracker", 80000, 1987, 12, 15); boss.setBonus(5000); System.out.println("boss.toString(): " + boss); System.out.println("carl.equals(boss): " + carl.equals(boss)); System.out.println("alice1.hashCode(): " + alice1.hashCode()); System.out.println("alice3.hashCode(): " + alice3.hashCode()); System.out.println("bob.hashCode(): " + bob.hashCode()); System.out.println("carl.hashCode(): " + carl.hashCode()); } }
運行結果以下:
實驗2:編程練習
1.定義抽象類Shape:
2.屬性:不可變常量double PI,值爲3.14;
3.方法:public double getPerimeter();public double getArea())。
讓Rectangle與Circle繼承自Shape類。
編寫double sumAllArea方法輸出形狀數組中的面積和和double sumAllPerimeter方法輸出形狀數組中的周長和。
main方法中
1)輸入整型值n,而後創建n個不一樣的形狀。若是輸入rect,則再輸入長和寬。若是輸入cir,則再輸入半徑。
2) 而後輸出全部的形狀的周長之和,面積之和。並將全部的形狀信息以樣例的格式輸出。
3) 最後輸出每一個形狀的類型與父類型,使用相似shape.getClass()(得到類型),shape.getClass().getSuperclass()(得到父類型);
思考sumAllArea和sumAllPerimeter方法放在哪一個類中更合適?
輸入樣例:
3 rect 1 1 rect 2 2 cir 1
輸出樣例:
18.28 8.14 [Rectangle [width=1, length=1], Rectangle [width=2, length=2], Circle [radius=1]] class Rectangle,class Shape class Rectangle,class Shape class Circle,class Shape
編程練習代碼以下:
package shape; import java.util.Scanner; public class Test { public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("個數"); int a = in.nextInt(); System.out.println("種類"); String rect="rect"; String cir="cir"; Shape[] num=new Shape[a]; for(int i=0;i<a;i++){ String input=in.next(); if(input.equals(rect)) { System.out.println("長和寬"); int length = in.nextInt(); int width = in.nextInt(); num[i]=new Rectangle(width,length); System.out.println("Rectangle["+"length:"+length+" width:"+width+"]"); } if(input.equals(cir)) { System.out.println("半徑"); int radius = in.nextInt(); num[i]=new Circle(radius); System.out.println("Circle["+"radius:"+radius+"]"); } } Test c=new Test(); System.out.println("求和"); System.out.println(c.sumAllPerimeter(num)); System.out.println(c.sumAllArea(num)); for(Shape s:num) { System.out.println(s.getClass()+","+s.getClass().getSuperclass()); } } public double sumAllArea(Shape score[]) { double sum=0; for(int i=0;i<score.length;i++) sum+= score[i].getArea(); return sum; } public double sumAllPerimeter(Shape score[]) { double sum=0; for(int i=0;i<score.length;i++) sum+= score[i].getPerimeter(); return sum; } }
demo:
package shape; abstract class Shape { //定義抽象父類Shape abstract double getPerimeter(); //定義求解周長的方法 abstract double getArea(); //定義求解面積的方法 } class Rectangle extends Shape{ private int length; private int width; public Rectangle(int length, int width) { this.length = length; this.width = width; } //繼承父類 double getPerimeter(){ //調用父類求周長的方法 return 2*(length+width); } double getArea(){ return length*width; //調用父類求面積的方法 } } class Circle extends Shape{ private int radius; public Circle(int radius) { this.radius = radius; } double getPerimeter(){ return 2 * Math.PI * radius; } double getArea(){ return Math.PI * radius * radius; } }
運行結果以下:
小結:
經過本週的學習,我瞭解到了什麼是繼承(新類繼承了舊類的方法和域,並添加了新的方法和域)以及它的特色和優勢,並經過老師的講解和課後的學習,大體明白了什麼是類、子類、超類,掌握了父類與子類的部分用法,學會了如何定義抽象類,使用super關鍵字等。初步的理解了繼承的結構層次和多態性的概念。在課下的學習中,經過示例程序以及查閱資料,也學到了不少有用的知識,但仍有不少疑惑,望老師能仔細講解。