繼承的使用時機:
當希望使用"所有的"父類別的內容
當希望擴增父類別的功能
當希望修改父類別的功能
這個Shape練習的關鍵在如何消除多餘的程式碼,還有練習組、父、子的繼承關係。繼承時,建構式和封裝為private的變數都無法繼承,若子類別需要用到這類的資源,就必須想辦法。
什麼辦法:
然後,有時候子類別有重複的程式碼的時候,不一定代表她們一定就要搬到父類別,因為有時候反而會造成共用其他這個父類別的子類別,必須實做這個method。
Shape3D.class
publicabstractclass Shape3D extends Shape{
privatedoubleradius;
public Shape3D(String name, double radius){
super(name);
this.setRadius(radius);
}
publicabstractdouble getVolume();
public void printVolume() {
String name = super.getName();
System.out.println(name + "的面積是=" + getVolume());
}
public double getRadius() {
returnradius;
}
public void setRadius(double radius) {
this.radius = radius;
}
}
Shape.class
publicabstractclass Shape {
private String name;
public String getName() {
returnname;
}
public Shape(String name){
this.setName(name);
}
public void setName(String name) {
if (name != null) {
this.name = name;
}
}
publicabstractdouble getArea();
public void printArea() {
System.out.println(name + "的面積是=" + getArea());
}
public Shape(){
}
}
Sphere.class
public class Sphere extends Shape3D {
public Sphere(String name, double radius) {
super(name); //這個地方會編譯失敗,程式會要求加入radius變數,因為super會往上層建構式(Shape)要求name,但SHape的建構式要求帶入兩個參數(String name, double radius) 所以這裡要寫成super(name, radius);才會成功
this.setRadius(radius);
}
public double getArea() {
return Math.PI * Math.pow(radius, 2) * 4; //這裡以下的radius都會失敗,因為radius這個變數已經搬到了shape,要引用他必須靠getRadius,去抓父類別的radius(所以其實是super.getRadius**),如果父類別也沒有,會再往祖父類別找
}
public void printArea() {
System.out.println(super.getName() + "的面積是=" + getArea());
}
public double getVolume() {
return (4 / 3) * Math.PI * Math.pow(radius, 3);
}
public void printVolume() {
System.out.println(super.getName() + "的面積是=" + getVolume());
}
}
Rectangle.java (老師版)
package com.hellopianoman.shape;
public class Rectangle extends Shape { // 子類別(sub class)繼承不到父類別(super class)的private屬性、private method, 也繼承不到父類別建構式(constructor)
private double length, width;
public Rectangle(String name, double length, double width) {
super(name); // 執行父類別建構式
this.setLength(length);
this.setWidth(width);
}
public double getArea() { // 此為覆寫了父類別的抽象方法, 或可說是實作了父類別的抽象方法
return this.length*this.width;
}
public double getLength() {
return length;
}
public void setLength(double length) {
this.length = length;
}
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
}
**在建立實體的時候(i.e. Rectangle = new Rectangle),JVM會自動將子類別的父類別一起建立實體