項目 | 內容 |
這個做業屬於哪一個課程 | https://www.cnblogs.com/nwnu-daizh/ |
這個做業要求在哪裏 | https://www.cnblogs.com/nwnu-daizh/p/11605051.htmlhtml |
做業的學習目標 |
|
第一部分:理論知識部分java
第五章 繼承(inheritance)算法
5.1 類、超類和子類編程
5.2 Object:全部類的超類數組
5.3 泛型數組列表ide
5.4 對象包裝器和自動打包函數
5.5 參數變量可變的方法學習
5.6 枚舉類測試
5.7 繼承設計的技巧this
5.1 類、超類和子類
繼承的特色:具備層次結構;子類繼承了父類的域和方法。
a)類繼承的格式:
class 新類名 extends 已有類名
b)已有類稱爲:超類(superclass)、基類(base class) 或父類(parent class)
新類稱做:子類(subclass)、派生類(derived class)或孩子類(child class)
c)通常來講,子類比超類擁有的功能更豐富。
d)super是一個指示編譯器調用超類方法的特有關鍵字,它不是一個對象的引用,不能將super賦給另外一個對象變量。
e) super關鍵字通常有兩個用途:一是調用超類的方法(格式:super.方法名()),二是調用超類的構造器(格式:super() )。
f)從一個超類擴展而來的類集合稱爲繼承層次(inheritance hierarchy)。在繼承層次中,某個類到其祖先的路徑被稱爲該類的繼承鏈(inheritance chain)。
注意:Java不支持多繼承
g)多態性:多態性泛指在程序中同一個符號在不一樣的狀況下具備不一樣解釋的現象。
java中,對象變量是多態的
h) 不容許繼承的類稱爲final類,在類的定義中用final修飾符加以說明,String類是final類的一個例子。不能擴展該類。
I)抽象類:包含一個或多個抽象方法的類必須聲明爲抽象類
抽象方法充當着佔位的角色,它們的具體實如今子類中。
抽象類不能被實例化,即不能建立對象,只能產生子類。
繼承小結
1)封裝、繼承、多態是面向對象的主要特徵。
2)繼承能夠提升代碼重用性,用extends關鍵字來實現。除構造方法以外,父類的全部方法和屬性都被子類繼承。
3)繼承創建了類與類間的關係,同時是多態特徵的前提。
4)java只支持單繼承,不直接支持多繼承(避免兩個父類出現同名方法的調用選擇困難)
5)abstract修飾的抽象類不能實例化爲對象,只能擴展子類;抽象類中的抽象方法充當着佔位的角色,它們的具體實如今子類中。
6)final類不容許繼承;類中final方法不容許被子類重寫。
5.2 Object:全部類的超類
a)Object類是Java中全部類的祖先——每個類都由它擴展而來。在不給出超類的狀況下,Java會自動把Object 做爲要定義類的超類。
b)可使用類型爲Object的變量指向任意類型的對象。但要對它們進行專門的操做都要進行類型轉換。
c)Object類中的equals方法用於測試某個對象是否同另外一個對象相等。它在Object類中的實現是判斷兩個對象是否具備相同的引用。若是兩個對象具備相同的引用,它們必定是相等的。
d)定義子類的equals方法時,可調用超類的equals方法。
super.equals(otherObject)
e) Object類中的hashCode方法導出某個對象的散列碼。散列碼是任意整數,表示對象的存儲地址。
兩個相等對象的散列碼相等。
f)Object類的toString方法返回一個表明該對象域值的字符串。定義子類的toString方法時,可先調用超類的toString方法。如:super.toString()
5.3 泛型數組列表
a) Java中,利用ArrayList類,可容許程序在運行時肯定數組的大小。
b)ArryList是一個採用類型參數的泛型類。爲指定數組列表保存元素的對象類型,須要用一對尖括號將數組元素的對象類名括起來加在後面。
ArryList<Employee> staff=new ArrayList<Employee>();
c)沒有<>的ArrayList將被認爲是一個刪去了類型參數的「原始」類型。
d)a.ArrayList定義
>ArrayList <T> 對象 = new ArrayList<T>();
>API : ArrayList的構造器
ArrayList<T>()構造一個空數組列表
ArrayList<T>(int initialCapacity)構造一個具備指定容量的空數組列表
5.4 對象包裝器和自動打包
a)全部基本數據類型都有着與之對應的預約義類,它們被稱爲對象包裝器。
b)對象包裝器類是不可變的,即一旦構造了包裝器,就不容許更改包裝在其中的值。且對象包裝器類仍是final,所以不能定義它們的子類。
c)使用對象包裝器的好處:
- 基本類型轉化爲對象
- 定義了一些有用的基本方法(static方法)
d)在JavaSE5.0中,能夠自動的將基本數據類型轉換爲包裝器類的對象,將這種變換稱爲自動打包
e)相反的,當對一個包裝器類的對象進行賦值或算法運算時,將會自動地拆包。
f)打包和拆包是編譯器承認的。
5.5 參數變量可變的方法
a)在Java SE 5.0之前的版本中,每一個Java方法都有固定數量的參數。然而,如今的版本提供了能夠用可變的參數數量調用的方法(稱爲「可變參 」方法)。
b 用戶本身能夠定義可變參數的方法,並將參數指定爲任意類型,甚至是基本類型。
5.6 枚舉類
a)聲明枚舉類
public enum Grade{A,B,C,D,E};
它包括一個關鍵字enum,一個新枚舉類型的名字 Grade以及爲Grade定義的一組值,這裏的值既非整型,亦非字符型。
b)枚舉類是一個類,它的隱含超類是java.lang.Enum。
c)枚舉值並非整數或其它類型,是被聲明的枚舉類的自身實例,例如A是Grade的一個實例
d)枚舉類不能有public修飾的構造函數,構造函數都是隱含private,編譯器自動處理。
e)枚舉值隱含都是由public、static、final修飾的,無須本身添加這些修飾符。
f)在比較兩個枚舉類型的值時i,永遠不須要調用equals方法,直接使用「==」進行相等比較。
5.7 繼承設計的技巧
a) 將公共操做和域放在超類。
b)不要使用受保護的域。
c)使用繼承實現「is-a」關係。
d)除非全部繼承的方法都有意義,不然就不要使用繼承。
e)在覆蓋方法時,不要改變預期的行爲。
f)使用多態,而非類型信息。
第二部分 :實驗部分
一、實驗目的與要求
(1) 理解繼承的定義;
(2) 掌握子類的定義要求
(3) 掌握多態性的概念及用法;
(4) 掌握抽象類的定義及用途。
二、實驗內容和步驟
實驗1: 導入第5章示例程序,測試並進行代碼註釋。
測試程序1:
Ÿ 在elipse IDE中編輯、調試、運行程序5-1 —5-3(教材152頁-153頁) ;
Ÿ 掌握子類的定義及用法;
Ÿ 結合程序運行結果,理解並總結OO風格程序構造特色,理解Employee和Manager類的關係子類的用途,並在代碼中添加註釋;
Ÿ 刪除程序中Manager類、ManagerTest類,背錄刪除類的程序代碼,在代碼錄入中理解父類與子類的關係和使用特色。
代碼以下:
ManagerTest.java
package texta;
public class ManagerTest
{
public static void main(String[] args)
{
// construct a Manager object
var boss = new Manager("Carl Cracker", 80000, 1987, 12, 15);
boss.setBonus(5000);
var staff = new Employee[3];
// fill the staff array with Manager and Employee objects
staff[0] = boss;
staff[1] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
staff[2] = new Employee("Tommy Tester", 40000, 1990, 3, 15);
// print out information about all Employee objects
for (Employee e : staff)
System.out.println("name=" + e.getName() + ",salary=" + e.getSalary());
}
}
Manager.java
package texta;
public class Manager extends 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 b)
{
bonus = b;
}
}
Employee.java
package texta;
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;
}
}
運行結果以下:
子類的定義及用法:一個父類能夠有多個子類,可是一個子類只能有一個父類。子類能夠經過extends關鍵字來繼承父類。
OO風格程序構造特色:封裝,繼承,多態,抽象。
測試程序2:
Ÿ 編輯、編譯、調試運行教材PersonTest程序(教材163頁-165頁);
Ÿ 掌握超類的定義及其使用要求;
Ÿ 掌握利用超類擴展子類的要求;
Ÿ 在程序中相關代碼處添加新知識的註釋;
Ÿ 刪除程序中Person類、PersonTest類,背錄刪除類的程序代碼,在代碼錄入中理解抽象類與子類的關係和使用特色。
代碼以下:
Student.java
package PersonTest;
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);
this.major = major;
}
public String getDescription()
{
return "a student majoring in " + major;
}
}
PersonTest.java
package PersonTest;
/**
* 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];
// 抽象類的聲明,但不能將抽象類實例化 ,實例化的是Person類的子類
// fill the people array with Student and Employee objects
people[0] = new Employee("Harry Hacker", 50000, 1989, 10, 1);
people[1] = new Student("Maria Morris", "computer science");
// print out names and descriptions of all Person objects
for (Person p : people)
System.out.println(p.getName() + ", " + p.getDescription());
}
}
Person.java
package PersonTest;
public abstract class Person
{
//包含一個或多個抽象方法的類被稱爲抽象類,由abstract關鍵字修飾 //通用的做用域和方法也放到了這裏,抽象類不能被實例化,但能夠被聲明
public abstract String getDescription();
private String name;
public Person(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
}
Employee.java
package PersonTest;
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);
}
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:
Ÿ 編輯、編譯、調試運行教材程序5-八、5-九、5-10,結合程序運行結果理解程序(教材174頁-177頁);
Ÿ 掌握Object類的定義及用法;
Ÿ 在程序中相關代碼處添加新知識的註釋。
程序代碼以下:
Employeea.java
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)
{
// 快速檢查對象是否相同 //這裏得到一個對象參數,第一個if語句判斷兩個引用是不是同一個,若是是那麼這兩個對象確定相等 if (this == otherObject) return true; // 若是顯式參數爲空,則必須返回false if (otherObject == null) return false; // getClass()方法是獲得對象的類,若是兩個對象的類不同,那麼就不相等 if (getClass() != otherObject.getClass()) return false; //如今咱們知道另外一個對象是非空僱員 //在以上判斷完成,再將獲得的參數對象強制轉換爲該對象,考慮到父類引用子類的對象的出現,而後再判斷對象的屬性是否相同 var other = (Employee) otherObject; //測試字段是否具備相同的值 return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDay, other.hireDay);
}
public int hashCode()
{
return Objects.hash(name, salary, hireDay);
}
public String toString()
{
return getClass().getName() + "[name=" + name + ",salary=" + salary + ",hireDay="
+ hireDay + "]";
}
}
EqualsTest.java
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)
{
var alice1 = new Employee("Alice Adams", 75000, 1987, 12, 15);
//建立對象,並初始化
var alice2 = alice1;
var alice3 = new Employee("Alice Adams", 75000, 1987, 12, 15);
var 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);
var carl = new Manager("Carl Cracker", 80000, 1987, 12, 15);
var 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());
}
}
Manager.java
package equals;
public class Manager extends 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;
var other = (Manager) otherObject;
// super.equals checked that this and other belong to the same class
return bonus == other.bonus;
}
public int hashCode()
{
return java.util.Objects.hash(super.hashCode(), bonus);
}
public String toString()
{
return super.toString() + "[bonus=" + bonus + "]";
}
}
運行結果以下:
實驗2:編程練習
Ÿ 定義抽象類Shape:
屬性:不可變常量double PI,值爲3.14;
方法: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方法放在哪一個類中更合適?
代碼以下:
Main.java
package text1;
import java.util.Scanner;
public class Main {
@SuppressWarnings({ "resource" })
public static void main(String[] args) {
int n;
Scanner in = new Scanner(System.in);
String rect = "rect";
String cir = "cir";
n= in.nextInt();
double[] c = new double[n];
Shape[] shapes= new Shape[n];
for(int i=0;i<n;i++)
{
String in2 = in.next();
if(in2.equals(rect))
{
double length = in.nextDouble();
double width = in.nextDouble();
shapes[i] = new Rectangle(width,length);
c[i]=1;
}
if(in2.equals(cir))
{
double radius = in.nextDouble();
shapes[i] = new Circle(radius);
c[i]=2;
}
}
System.out.println(sumAllPerimeter(shapes));
System.out.println(sumAllArea(shapes));
System.out.printf("[");
for(int i=0;i<n;i++)
{
if(c[i]==1)
System.out.printf("Rectangle["+"length:"+Rectangle.length+" width:"+Rectangle.width+"]");
else
System.out.printf("Circle["+"radius:"+Circle.radius+"]");
if(n!=1&&i<n-1)
System.out.printf(",");
}
System.out.println("]");
for(Shape s:shapes)
{
System.out.println(s.getClass()+", "+s.getClass().getSuperclass());
}
}
private static double sumAllPerimeter(Shape shape2[]) {
double sum = 0;
for(int i = 0;i<shape2.length;i++)
sum+= shape2[i].getPerimeter();
return sum;
}
private static double sumAllArea(Shape shape1[]) {
double sum = 0;
for(int i = 0;i<shape1.length;i++)
sum+=shape1[i].getArea();
return sum;
}
}
Shape.java
package text1;
public abstract class Shape {
final double PI =3.14;
public abstract double getPerimeter();
public abstract double getArea();
public abstract double getName();
}
Rectangle.java
package text1;
public class Rectangle extends Shape {
static double width;
static double length;
public Rectangle(double w,double l)
{
width = w;
length = l;
}
public double getPerimeter()
{
double Perimeter = (width+length)*2;
return Perimeter;
}
public double getArea()
{
double Area = width*length;
return Area;
}
public String toString()
{
return getClass().getName() + "[ width=" + width + "]"+ "[length=" + length + "]";
}
public double getN()
{
double a=1;
return a;
}
@Override
public double getName() {
// TODO Auto-generated method stub
return 0;
}
}
Circle.java
package text1;
public class Circle extends Shape {
static double radius;
public Circle(double r)
{
radius = r;
}
public double getPerimeter()
{
double Perimeter = 2*PI*radius;
return Perimeter;
}
public double getArea()
{
double Area = PI*radius*radius;
return Area;
}
public String toString()
{
return getClass().getName() + "[radius=" + radius + "]";
}
@Override
public double getName() {
// TODO Auto-generated method stub
return 0;
}
}
運行結果以下:
第三部分:實驗總結
本次學習理解了Java程序設計中類與對象的關係,理解OO程序設計的特徵:繼承和多態,並學會採用繼承定義類設計程序,掌握利用了父類定義子類的語法規則及對象使用要求。在完成實驗過程當中理解了繼承的定義,掌握子類的定義要求,多態性的概念及用法,抽象類的定義及用途。經過本身動手敲代碼讓我更加深入的理解了本章的知識。但本章知識比較多也比較重要,仍須要多多增強鞏固,繼續努力。