Java เวอร์ชันใหม่ทุกเวอร์ชันแตกต่างจากเวอร์ชันก่อนหน้า ต่อไปนี้คือตัวอย่างการเปลี่ยนแปลงเนื้อหาที่เรากล่าวถึง: ก่อน Java 5 ภาษาไม่มี
ในทำนองเดียวกัน Java 8 แตกต่างจาก Java 7 อย่างเห็นได้ชัด บทเรียนส่วนใหญ่ของเราเขียนขึ้นสำหรับเวอร์ชันที่ 7 ของภาษา แต่แน่นอนว่าเราจะไม่ละเลยนวัตกรรมที่สำคัญ เนื่องจากเราได้พูดถึงอินเทอร์เฟ ซในบทเรียนนี้แล้ว เราจะพิจารณาการอัปเดตหนึ่งรายการ นั่นคือวิธีเริ่มต้นในอินเทอร์เฟซ คุณรู้อยู่แล้วว่า อิน เทอร์เฟซไม่ได้ใช้ลักษณะการทำงาน หน้าที่ของมันคือการอธิบายลักษณะการทำงานที่ออบเจกต์ทั้งหมดที่ใช้งานต้องมี. แต่นักพัฒนามักพบสถานการณ์ที่การใช้งานเมธอดเหมือนกันในทุกคลาส ลองพิจารณาตัวอย่างรถเก่าของเรา:
enum
s 
public interface Car {
public void gas();
public void brake();
}
public class Sedan implements Car {
@Override
public void gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class Truck implements Car {
@Override
public void gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class F1Car implements Car {
@Override
public void gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
"ในความเห็นของคุณ อะไรคือปัญหาหลักของโค้ดนี้ คุณอาจสังเกตเห็นว่าเราเขียนโค้ดซ้ำๆ กันหลายชุด ปัญหานี้พบได้ทั่วไปในการเขียนโปรแกรม และคุณต้องหลีกเลี่ยงปัญหานี้ เป็นอีกเรื่องหนึ่งที่วิธีแก้ปัญหาเฉพาะนั้นไม่เคยมีมาก่อน Java 8 เปิดตัวแล้ว ด้วยเวอร์ชันนี้ทำให้สามารถระบุเมธอดเริ่มต้นและปรับใช้ได้โดยตรงภายในอินเทอร์เฟซ นี่คือวิธี:
public interface Car {
public default void gas() {
System.out.println("Gas!");
}
public default void brake() {
System.out.println("Brake!");
}
}
public class Sedan implements Car {
}
public class Truck implements Car {
}
public class F1Car implements Car {
}
ตอนนี้gas()
และbrake()
วิธีการ ซึ่งเหมือนกันกับรถยนต์ทุกคัน ถูกย้ายไปที่อินเทอร์เฟซแล้ว ไม่จำเป็นต้องใช้รหัสซ้ำ ยิ่งไปกว่านั้น ยังมีวิธีการในแต่ละคลาสอีกด้วย!
public class Main {
public static void main(String[] args) {
F1Car f1Car = new F1Car();
Sedan sedan = new Sedan();
Truck truck = new Truck();
truck.gas();
sedan.gas();
f1Car.brake();
}
}
เกิดอะไรขึ้นถ้ามี 100 คลาสที่มีgas()
เมธอด แต่มีเพียง 99 คลาสเท่านั้นที่มีพฤติกรรมเหมือนกัน นั่นทำลายทุกอย่างและทำให้วิธีการเริ่มต้นไม่เหมาะกับสถานการณ์นี้หรือไม่? แน่นอน ไม่ใช่ :) วิธีการเริ่มต้นในอินเทอร์เฟซสามารถแทนที่ได้ในลักษณะเดียวกับวิธีปกติ
public class UnusualCar implements Car {
@Override
public void gas() {
System.out.println("This car accelerates differently!");
}
@Override
public void brake() {
System.out.println("This car decelerates differently!");
}
}
รถยนต์ประเภทอื่น ๆ ทั้งหมด 99 คันจะใช้วิธีเริ่มต้นและUnusualCar
คลาสซึ่งเป็นข้อยกเว้นจะไม่ทำให้เสียภาพรวมและกำหนดพฤติกรรมของตัวเองอย่างใจเย็น การสืบทอดอินเทอร์เฟซหลายรายการ ดังที่คุณทราบแล้ว Java ไม่สนับสนุนการสืบทอดหลายรายการ มีเหตุผลหลายประการสำหรับเรื่องนี้ เราจะดูรายละเอียดในบทเรียนแยกต่างหาก รองรับภาษาอื่นๆ เช่น C++ หากไม่มีการสืบทอดหลายรายการ ปัญหาร้ายแรงจะเกิดขึ้น: วัตถุชิ้นหนึ่งสามารถมีลักษณะและ 'พฤติกรรม' ที่แตกต่างกันได้หลายอย่าง นี่คือตัวอย่างจากชีวิต: เราเป็นลูกของพ่อแม่ นักเรียนกับครู และคนไข้กับหมอของเรา ในชีวิต เรามีบทบาทที่แตกต่างกัน ดังนั้น จึงมีพฤติกรรมที่แตกต่างกัน แน่นอนว่าเราจะไม่พูดกับครูในลักษณะเดียวกับที่เราพูดกับเพื่อนสนิทของเรา ลองแปลสิ่งนี้เป็นรหัส ลองนึกภาพว่าเรามีสองคลาส: บ่อน้ำและกรงนกขนาดใหญ่ สำหรับสระน้ำ เราต้องการนกน้ำ สำหรับกรงนก เราต้องการนกที่บินได้ ในการทำเช่นนี้ เราได้สร้างคลาสพื้นฐานสองคลาส:FlyingBird
และWaterfowl
.
public class Waterfowl {
}
public class FlyingBird {
}
ดังนั้น เราจะส่งนกที่มีคลาสสืบทอดFlyingBird
ไปยังกรงนกใหญ่ และเราจะส่งนกที่สืบทอดWaterfowl
ไปยังบ่อน้ำ ทุกอย่างดูเหมือนง่ายมาก แต่เราจะส่งเป็ดไปที่ไหน? มันว่ายน้ำและบิน และเราไม่มีหลายมรดก โชคดีที่ Java รองรับการใช้งานอินเทอร์เฟซที่หลากหลาย แม้ว่าคลาสจะไม่สามารถสืบทอดพาเรนต์หลายตัวได้ แต่ก็สามารถใช้หลายอินเทอร์เฟซได้อย่างง่ายดาย! เป็ดของเราสามารถเป็นได้ทั้งนกบินและนกน้ำ :) เราเพียงแค่ต้องสร้างFlyingBird
และWaterfowl
เชื่อมต่อมากกว่าชั้นเรียนเพื่อให้ได้ผลลัพธ์ที่ต้องการ
public class Duck implements FlyingBird, Waterfowl {
// The methods of both interfaces can be easily combined into one class
@Override
public void fly() {
System.out.println("Fly!");
}
@Override
public void swim() {
System.out.println("Swim!");
}
}
ดังนั้น โปรแกรมของเราจึงรักษาความยืดหยุ่นของคลาสไว้ และเมื่อใช้ร่วมกับเมธอดดีฟอลต์ ความสามารถของเราในการกำหนดพฤติกรรมของอ็อบเจกต์จึงแทบไม่มีขีดจำกัด! :)
GO TO FULL VERSION