สวัสดี! ในบทที่แล้ว เราได้ทำความคุ้นเคยกับแนวคิดเรื่องการสืบทอดมาพอสังเขปแล้ว วันนี้เราจะพูดถึงหัวข้อนี้อีกครั้ง แต่จะไม่ลึกเกินไป เรายังคงมีบทเรียนที่ละเอียดกว่านี้ในอนาคต วันนี้เราจะมาดูตัวอย่างที่ใช้งานได้จริงบางส่วนและทำความคุ้นเคยกับโอเปอเรเตอร์ที่น่าสนใจใน Java
การสืบทอดเป็นกลไกการเขียนโปรแกรม (รวมถึงใน Java) ที่ให้คุณประกาศคลาสใหม่ตามคลาสที่มีอยู่ จากนั้นคลาสที่ได้รับจะเข้าถึงฟิลด์และเมธอดของคลาสพาเรนต์ ทำไมเราต้องการสิ่งนี้ ลองจินตนาการว่าคุณต้องสร้างคลาสรถหลายคลาสในโปรแกรม: Truck, RaceCar, Sedan, Pickup, etc. ก่อนที่คุณจะเขียนโค้ดใดๆ คุณรู้แน่นอนว่าคลาสเหล่านี้มีหลายอย่างที่เหมือนกัน: รถยนต์ทุกคันมีรุ่น ชื่อ ปีที่ผลิต ขนาดเครื่องยนต์ ความเร็วสูงสุด ฯลฯ (ไม่ต้องพูดถึงความจริงที่ว่าพวกเขาทั้งหมดมีล้อและชิ้นส่วนอื่น ๆ เหมือนกัน) ในสถานการณ์นี้ คุณสามารถ:
มรดก
ดังนั้นมรดกคืออะไร?
- สร้างฟิลด์เหล่านี้ในแต่ละคลาส (เพิ่มลงในคลาสรถใหม่แต่ละคลาสเมื่อคุณสร้าง)
- นำฟิลด์ทั่วไปของรถยนต์ทุกคันมาไว้ใน
Car
คลาสหลัก จากนั้นใช้คีย์เวิร์ดขยายเพื่อรับคลาสทั้งหมดสำหรับรถยนต์บางประเภทจากCar
คลาส นั้น
public class Car {
private String model;
private int maxSpeed;
private int yearOfManufacture;
public Car(String model, int maxSpeed, int yearOfManufacture) {
this.model = model;
this.maxSpeed = maxSpeed;
this.yearOfManufacture = yearOfManufacture;
}
}
public class Truck extends Car {
public Truck(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
public class Sedan extends Car {
public Sedan(String model, int maxSpeed, int yearOfManufacture) {
super(model, maxSpeed, yearOfManufacture);
}
}
อย่างน้อยที่สุด เราหลีกเลี่ยงการทำซ้ำโค้ดโดยไม่จำเป็น (และเราควรพยายามอย่างเต็มที่เมื่อเขียนโปรแกรม) นอกจากนี้ เรายังมีโครงสร้างคลาสที่เรียบง่ายและเข้าใจได้ โดยฟิลด์ทั้งหมดที่ใช้ร่วมกันกับรถยนต์ทุกคันจะรวมอยู่ในคลาสเดียว หากรถบรรทุกมีช่องพิเศษที่รถคันอื่นไม่มี สามารถประกาศได้ในTruck
ชั้นเรียน เช่นเดียวกับวิธีการ รถยนต์ทุกคันมีลักษณะการทำงานทั่วไปบางอย่างที่สามารถอธิบายได้ด้วยวิธีการต่างๆ เช่น สตาร์ทรถ เร่งความเร็ว/เบรก ฯลฯ วิธีการทั่วไปเหล่านี้สามารถรวมเข้ากับคลาสแม่ได้Car
และรถยนต์แต่ละประเภทสามารถกำหนดการกระทำเฉพาะในคลาสที่ได้รับมา .
public class Car {
public void gas() {
// Accelerate
}
public void brake() {
// Brake
}
}
public class F1Car extends Car {
public void pitStop() {
// Only race cars make pit stops
}
public static void main(String[] args) {
F1Car formula1Car = new F1Car();
formula1Car.gas();
formula1Car.pitStop();
formula1Car.brake();
}
}
เราได้เพิ่มวิธีการทั่วไปสำหรับรถยนต์ทุกคันในCar
คลาส แต่ดูที่F1Car
คลาสซึ่งเป็นตัวแทนของรถแข่ง "Formula 1" การหยุดเข้าพิท (การหยุดเพื่อบำรุงรักษารถอย่างเร่งด่วน) จะทำเฉพาะในสนามแข่งเท่านั้น ดังนั้นเราจึงเพิ่มฟังก์ชันเฉพาะนี้ให้กับคลาสที่ได้รับมาที่เกี่ยวข้อง 
ตัวดำเนินการอินสแตนซ์
ใน Java มีโอเปอเรเตอร์พิเศษอินสแตนซ์สำหรับตรวจสอบว่าออบเจกต์ถูกสร้างขึ้นตามคลาสใดคลาสหนึ่งหรือไม่ จะคืนค่าจริงหรือเท็จขึ้นอยู่กับผลการตรวจสอบ มาดูกันว่ามันทำงานอย่างไรโดยใช้คลาสในตัวอย่างรถของเรา:
public class Truck extends Car {
public static void main(String[] args) {
Truck truck = new Truck();
System.out.println(truck instanceof Car);
}
}
ผลลัพธ์: จริง ตัวinstanceof
ดำเนินการส่งคืนจริงเนื่องจากเรามีTruck
วัตถุ และรถบรรทุกทั้งหมดเป็นรถยนต์ คลาสTruck
มาจากCar
คลาส รถบรรทุกทั้งหมดถูกสร้างขึ้นตามผู้ปกครองทั่วไปคือCar
คลาส ดูวิธีinstanceof
การใช้ตัวดำเนินการ อย่างใกล้ชิด คุณเขียนโดยไม่มีจุดเนื่องจากเป็นโอเปอเรเตอร์ ไม่ใช่เมธอด ("object instanceof Class") มาลองวิธีอื่นกัน:
public static void main(String[] args) {
Car car = new Car();
System.out.println(car instanceof Truck);
}
ผลลัพธ์: เท็จ คลาสCar
(และวัตถุรถยนต์) ไม่ได้มาจากTruck
คลาส รถบรรทุกทุกคันเป็นรถยนต์ แต่ไม่ใช่ทุกคันเป็นรถบรรทุก Car
วัตถุไม่ได้ขึ้นอยู่กับTruck
ชั้นเรียน อีกหนึ่งตัวอย่าง:
public static void main(String[] args) {
Car car = new Car();
Truck truck = new Truck();
System.out.println(car instanceof Object && truck instanceof Object);
}
ผลลัพธ์: จริง ตรรกะที่นี่ก็เรียบง่ายเช่นกัน: คลาสทั้งหมดใน Java รวมถึงคลาสที่คุณสร้าง สืบเชื้อสายมาจากคลาสObject
(แม้ว่าคุณจะไม่ได้เขียนว่า "extends Object" แต่ก็บอกเป็นนัยอยู่แล้ว) สิ่งนี้จะมีประโยชน์อย่างไรและเมื่อใด instanceof
โดยทั่วไปจะใช้โอเปอเรเตอร์เมื่อแทนที่equals()
เมธอด ตัวอย่างเช่น ต่อไปนี้คือวิธีequals
นำเมธอดไปใช้ในString
คลาส:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String) anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
ก่อนเปรียบเทียบ a String
กับวัตถุที่ส่งผ่าน เมธอดจะทดสอบเพื่อดูว่าวัตถุนั้นเป็นสตริงหรือไม่ จากนั้นจึงเริ่มเปรียบเทียบคุณสมบัติของวัตถุทั้งสอง หากไม่มีการทดสอบนี้ วัตถุใด ๆ ที่มีค่าและ ฟิลด์ ความยาวสามารถส่งผ่านไปยังเมธอดและเปรียบเทียบกับสตริงได้ ซึ่งแน่นอนว่าจะผิด
GO TO FULL VERSION