อะไรคือ "ระดับสุดท้าย" ใน Java?


569

ฉันกำลังอ่านหนังสือเกี่ยวกับ Java และมันบอกว่าคุณสามารถประกาศทั้งชั้นfinalได้ ฉันไม่สามารถคิดถึงสิ่งที่ฉันจะใช้สิ่งนี้

ฉันเพิ่งใหม่กับการเขียนโปรแกรมและฉันสงสัยว่าโปรแกรมเมอร์ใช้สิ่งนี้กับโปรแกรมของพวกเขาหรือไม่หรือไม่ ถ้าพวกเขาทำพวกเขาจะใช้เมื่อใดฉันจึงสามารถเข้าใจได้ดีขึ้นและรู้ว่าควรใช้เมื่อไร

ถ้า Java เป็นเชิงวัตถุและคุณประกาศคลาสfinalมันจะไม่หยุดความคิดของคลาสที่มีคุณสมบัติของวัตถุหรือไม่

คำตอบ:


531

ก่อนอื่นฉันขอแนะนำบทความนี้: Java: เมื่อใดที่จะสร้างคลาสสุดท้าย


ถ้าพวกเขาทำพวกเขาจะใช้เมื่อใดฉันจึงสามารถเข้าใจได้ดีขึ้นและรู้ว่าควรใช้เมื่อไร

finalระดับเป็นเพียงระดับที่ไม่สามารถขยายได้

(ไม่ได้หมายความว่าการอ้างอิงทั้งหมดไปยังวัตถุของคลาสจะทำหน้าที่เหมือนกับว่าพวกเขาถูกประกาศเป็นfinal)

เมื่อการประกาศคลาสมีประโยชน์จะครอบคลุมคำตอบของคำถามนี้:

ถ้า Java เป็นเชิงวัตถุและคุณประกาศคลาสfinalมันจะไม่หยุดความคิดของคลาสที่มีคุณสมบัติของวัตถุหรือไม่

ในบางแง่ใช่

การทำเครื่องหมายชั้นเรียนเป็นขั้นสุดท้ายทำให้คุณปิดใช้งานคุณสมบัติที่ทรงพลังและยืดหยุ่นของภาษาสำหรับส่วนนั้นของรหัส อย่างไรก็ตามบางคลาสไม่ควร (และในบางกรณีไม่สามารถ ) ได้รับการออกแบบมาเพื่อให้มีการจัดคลาสย่อยเข้าด้วยกันอย่างดี ในกรณีเหล่านี้มันสมเหตุสมผลที่จะทำเครื่องหมายคลาสว่าสุดท้ายแม้ว่าจะ จำกัด OOP (โปรดจำไว้ว่าชั้นเรียนสุดท้ายยังสามารถขยายชั้นเรียนอื่นที่ไม่ใช่ชั้นเรียนได้อีก)


39
เพื่อเพิ่มคำตอบหนึ่งในหลักการของ Effective Java คือการสนับสนุนการแต่งเพลงมากกว่าการสืบทอด การใช้คำหลักสุดท้ายยังช่วยในการบังคับใช้หลักการนั้น
Riggy

9
"คุณทำเพื่อเหตุผลด้านประสิทธิภาพและความปลอดภัยเป็นหลัก" ฉันได้ยินคำพูดนี้บ่อยครั้ง (แม้แต่วิกิพีเดียก็ยังระบุไว้) แต่ฉันก็ยังไม่เข้าใจเหตุผลของการโต้แย้งนี้ มีใครบางคนสนใจที่จะอธิบายว่า java.lang.String ที่ไม่ใช่ครั้งสุดท้ายจะกลายเป็นว่าไม่มีประสิทธิภาพหรือไม่ปลอดภัยหรือไม่?
MRA

27
@MRA หากฉันสร้างวิธีการที่ยอมรับสตริงเป็นพารามิเตอร์ฉันคิดว่ามันไม่เปลี่ยนรูปเพราะ Strings เป็น ด้วยเหตุนี้ฉันรู้ว่าฉันสามารถเรียกวิธีการใด ๆ บนวัตถุ String ได้อย่างปลอดภัยและไม่เปลี่ยน String ที่ส่งผ่าน ถ้าฉันจะขยาย String และเปลี่ยนการใช้งานของสตริงย่อยเพื่อเปลี่ยน String จริงแล้ววัตถุ String ที่คุณคาดว่าจะไม่เปลี่ยนรูปจะไม่เปลี่ยนรูปอีกต่อไป
Cruncher

1
@Sortofabeginner และทันทีที่คุณบอกว่าคุณต้องการให้เมธอดและฟิลด์ทั้งหมดเป็นที่สิ้นสุดดังนั้นคุณจึงสามารถสร้างคลาสด้วยฟังก์ชันการทำงานเพิ่มเติม ... ณ จุดนี้คุณอาจสร้างคลาสที่มีสตริงและ สร้างวิธีการที่ทำงานบนสตริงนั้น
Cruncher

1
@Shay final (ท่ามกลางสิ่งอื่น ๆ ) ถูกนำมาใช้เพื่อทำให้วัตถุไม่เปลี่ยนรูปดังนั้นฉันจะไม่พูดว่าพวกเขาไม่มีอะไรเกี่ยวข้องกัน ดูที่นี่docs.oracle.com/javase/tutorial/essential/concurrency/…
Celeritas

184

ใน Java รายการที่มี finalตัวแก้ไขไม่สามารถเปลี่ยนแปลงได้!

ซึ่งรวมถึงคลาสสุดท้ายตัวแปรสุดท้ายและวิธีสุดท้าย:

  • ชั้นสุดท้ายไม่สามารถขยายได้โดยชั้นอื่น ๆ
  • ตัวแปรสุดท้ายไม่สามารถกำหนดค่าอื่นได้อีกครั้ง
  • วิธีสุดท้ายไม่สามารถเขียนทับได้

40
คำถามที่เกิดขึ้นจริงทำไมไม่สิ่งที่
Francesco Menzani

8
คำสั่ง "ใน Java รายการที่มีfinalตัวแก้ไขไม่สามารถเปลี่ยนแปลงได้!" เป็นหมวดหมู่มากเกินไปและในความเป็นจริงไม่ถูกต้องทั้งหมด ดังที่ Grady Booch กล่าวไว้ว่า "วัตถุมีสถานะพฤติกรรมและเอกลักษณ์" ในขณะที่เราไม่สามารถเปลี่ยนข้อมูลประจำตัวของวัตถุได้เมื่อการอ้างอิงถูกทำเครื่องหมายเป็นขั้นสุดท้ายเรามีโอกาสที่จะเปลี่ยนสถานะของมันโดยการกำหนดค่าใหม่ให้กับfinalเขตข้อมูลที่ไม่ใช่เขตข้อมูล การวางแผนเพื่อรับการรับรอง Oracle Java (เช่น 1Z0-808 เป็นต้น) ควรเก็บไว้ในใจเพราะอาจมีคำถามในด้านนี้ในการสอบ ...
Igor Soudakevitch

33

สถานการณ์สมมติหนึ่งที่สุดท้ายเป็นสิ่งสำคัญเมื่อคุณต้องการป้องกันการสืบทอดคลาสเพื่อเหตุผลด้านความปลอดภัย วิธีนี้ช่วยให้คุณมั่นใจได้ว่ารหัสที่คุณกำลังเรียกใช้นั้นไม่สามารถถูกแทนที่ได้โดยบุคคลอื่น

อีกสถานการณ์หนึ่งสำหรับการปรับให้เหมาะสม: ฉันดูเหมือนจะจำได้ว่าคอมไพเลอร์ Java แทรกการเรียกฟังก์ชันบางอย่างจากคลาสสุดท้าย ดังนั้นหากคุณโทรหาa.x()และ a ถูกประกาศfinalเรารู้ ณ เวลารวบรวมว่าโค้ดจะเป็นอะไรและสามารถอินไลน์เข้าสู่ฟังก์ชันการโทรได้ ฉันไม่รู้ว่าจะทำจริงหรือไม่ แต่สุดท้ายก็เป็นไปได้


7
การทำอินไลน์จะทำโดยคอมไพเลอร์ทันเวลาเท่านั้นที่รันไทม์ มันทำงานได้โดยไม่ต้องปิดท้ายเช่นกัน แต่คอมไพเลอร์ JIT มีงานอีกเล็กน้อยที่ต้องทำเพื่อให้แน่ใจว่าไม่มีคลาสที่ขยายเพิ่ม (หรือคลาสที่ขยายเหล่านี้ไม่ได้สัมผัสวิธีนี้)
Paŭlo Ebermann

บทความที่ดีเกี่ยวกับการinline
Josh Hemann

24

ตัวอย่างที่ดีที่สุดคือ

String สุดท้ายระดับสาธารณะ

ซึ่งเป็นชั้นที่ไม่เปลี่ยนรูปและไม่สามารถขยายได้ แน่นอนว่ามีมากกว่าเพียงแค่ทำให้ชั้นสุดท้ายที่จะไม่เปลี่ยนรูป


Hehe บางครั้งมันปกป้องนักพัฒนา Rube Goldergian จากตัวเอง
Zoidberg

16

การอ่านที่เกี่ยวข้อง: หลักการเปิดโดย Bob Martin

คำพูดที่สำคัญ:

หน่วยงานซอฟต์แวร์ (คลาส, โมดูล, ฟังก์ชั่น, อื่น ๆ ) ควรจะเปิดสำหรับส่วนขยาย แต่ปิดสำหรับการปรับเปลี่ยน

finalคำหลักเป็นวิธีการที่จะบังคับใช้ใน Java ไม่ว่าจะใช้วิธีการหรือในชั้นเรียน


6
@Sean: ไม่ได้ประกาศว่ามันfinalปิดชั้นเรียนสำหรับการขยายมากกว่าเปิด? หรือฉันกำลังใช้มันอย่างแท้จริง?
Goran Jovic

4
@Goran ทั่วโลกสมัครขั้นสุดท้ายแล้วใช่ ที่สำคัญคือการเลือกใช้ขั้นสุดท้ายในสถานที่ที่คุณไม่ต้องการปรับเปลี่ยน (และแน่นอนเพื่อให้ตะขอที่ดีสำหรับการขยาย)
ฌอนแพทริคฟลอยด์

26
ใน OCP "การแก้ไข" หมายถึงการแก้ไขซอร์สโค้ดและ "ส่วนขยาย" หมายถึงการสืบทอดการใช้งาน ดังนั้นการใช้งานfinalในการประกาศคลาส / เมธอดจะไม่สมเหตุสมผลถ้าคุณต้องการให้โค้ดการใช้งานถูกปิดเพื่อการแก้ไข แต่เปิดสำหรับการขยายโดยการสืบทอด
Rogério

1
@Rogerio ฉันได้ยืมอ้างอิง (และการตีความ) จากฤดูใบไม้ผลิกรอบอ้างอิง (MVC) IMHO สิ่งนี้สมเหตุสมผลมากกว่าเวอร์ชันดั้งเดิมมาก
ฌอนแพทริคฟลอยด์

ส่วนต่อขยายตาย ไร้ประโยชน์ ทลาย ทำลาย ฉันไม่สนใจ OCP ไม่มีข้อแก้ตัวสำหรับการขยายชั้นเรียน
Josh Woodcock

15

หากคุณคิดว่าลำดับชั้นของคลาสเป็นต้นไม้ (เหมือนใน Java) คลาสนามธรรมสามารถเป็นได้เฉพาะสาขาและคลาสสุดท้ายคือคลาสที่เป็นใบไม้เท่านั้น คลาสที่ไม่อยู่ในหมวดหมู่เหล่านั้นสามารถเป็นได้ทั้งกิ่งและใบไม้

ไม่มีการละเมิดหลักการ OO ที่นี่สุดท้ายคือการให้สมมาตรที่ดี

ในทางปฏิบัติคุณต้องการใช้ขั้นสุดท้ายหากคุณต้องการให้ออบเจ็กต์ของคุณไม่เปลี่ยนรูปหรือถ้าคุณกำลังเขียน API เพื่อส่งสัญญาณไปยังผู้ใช้ API ว่าคลาสนั้นไม่ได้มีไว้สำหรับขยาย


13

คำหลักfinalนั้นหมายถึงบางสิ่งเป็นที่สุดและไม่ควรมีการแก้ไข แต่อย่างใด หากชั้นเรียนถ้าทำเครื่องหมายfinalแล้วมันจะไม่สามารถขยายหรือชั้นย่อย แต่คำถามคือทำไมเราถึงทำเครื่องหมายชั้นเรียนfinal? IMO มีสาเหตุหลายประการ:

  1. มาตรฐาน:บางคลาสทำหน้าที่ฟังก์ชั่นมาตรฐานและพวกเขาไม่ได้ตั้งใจที่จะแก้ไขเช่นคลาสที่ทำหน้าที่ต่าง ๆ ที่เกี่ยวข้องกับการจัดการสตริงหรือฟังก์ชั่นทางคณิตศาสตร์ ฯลฯ
  2. เหตุผลด้านความปลอดภัย : บางครั้งเราเขียนคลาสที่มีฟังก์ชั่นการรับรองความถูกต้องและรหัสผ่านที่หลากหลายและเราไม่ต้องการให้บุคคลอื่นแก้ไข

ฉันได้ยินมาว่าคลาสการทำเครื่องหมายfinalช่วยเพิ่มประสิทธิภาพ แต่ตรงไปตรงมาฉันไม่สามารถหาข้อโต้แย้งนี้เพื่อให้มีน้ำหนักมาก

ถ้า Java เป็นเชิงวัตถุและคุณประกาศคลาสสุดท้ายมันจะไม่หยุดความคิดของคลาสที่มีคุณสมบัติของวัตถุหรือไม่?

อาจจะใช่ แต่บางครั้งนั่นเป็นจุดประสงค์ บางครั้งเราทำเช่นนั้นเพื่อให้เกิดประโยชน์ที่มากขึ้นของความปลอดภัย ฯลฯ โดยการลดความสามารถของคลาสนี้เพื่อขยาย แต่คลาสสุดท้ายก็ยังสามารถขยายชั้นหนึ่งได้ถ้าต้องการ

ในหมายเหตุด้านข้างเราควรชอบการแต่งมากกว่าการสืบทอดและfinalคำสำคัญจริง ๆ แล้วช่วยในการบังคับใช้หลักการนี้


6

ระวังเมื่อคุณสร้างคลาส "สุดท้าย" เพราะถ้าคุณต้องการเขียนการทดสอบหน่วยสำหรับคลาสสุดท้ายคุณไม่สามารถคลาสย่อยคลาสสุดท้ายนี้เพื่อใช้เทคนิคการแบ่งการพึ่งพา "Subclass และ Override Method" ที่อธิบายไว้ในหนังสือของ Michael C. Feathers "การทำงานอย่างมีประสิทธิภาพด้วยรหัสมรดก" . ในหนังสือเล่มนี้เฟเธอร์พูดว่า "อย่างจริงจังมันง่ายที่จะเชื่อว่าการปิดผนึกและครั้งสุดท้ายเป็นความผิดที่ผิดพลาดซึ่งพวกเขาไม่ควรถูกเพิ่มเข้าไปในภาษาการเขียนโปรแกรม แต่ความผิดจริงเกิดขึ้นกับเราเมื่อเราพึ่งพาโดยตรง ห้องสมุดที่อยู่เหนือการควบคุมของเราเราเพียงแค่ขอปัญหา”


6

final class สามารถหลีกเลี่ยงการทำลาย API สาธารณะเมื่อคุณเพิ่มวิธีการใหม่

สมมติว่าในรุ่นที่ 1 ของBaseคลาสคุณทำ:

public class Base {}

และลูกค้าทำ:

class Derived extends Base {
    public int method() { return 1; }
}

ถ้าหากในเวอร์ชั่น 2 คุณต้องการเพิ่มmethodวิธีการBase:

class Base {
    public String method() { return null; }
}

มันจะทำลายรหัสลูกค้า

หากเราใช้final class Baseแทนลูกค้าจะไม่สามารถสืบทอดและการเพิ่มเมธอดจะไม่ทำลาย API


5

ถ้าคลาสนั้นถูกทำเครื่องหมายแสดงfinalว่าโครงสร้างของคลาสไม่สามารถแก้ไขได้โดยสิ่งภายนอก ที่นี่คือสิ่งที่มองเห็นได้มากที่สุดคือเมื่อคุณทำการถ่ายทอดทางพันธุกรรมแบบดั้งเดิมโดยทั่วไปแล้วclass B extends Aจะไม่ทำงาน มันเป็นวิธีการป้องกันบางส่วนของรหัสของคุณ(เท่า) (ขอบเขต)

ในการชี้แจงการทำเครื่องหมายคลาสfinalไม่ได้ทำเครื่องหมายฟิลด์finalเป็นเช่นนั้นไม่ได้ป้องกันคุณสมบัติของวัตถุ แต่โครงสร้างคลาสจริงแทน


1
คุณสมบัติของวัตถุหมายถึงอะไร มันหมายความว่าฉันสามารถแก้ไขตัวแปรสมาชิกของคลาสได้หรือไม่ถ้าคลาสนั้นถูกประกาศให้เป็นที่สิ้นสุด? ดังนั้นจุดประสงค์เดียวของคลาสสุดท้ายคือเพื่อป้องกันการสืบทอด
Adam Lyu

5

วิธีแก้ไขปัญหาระดับสุดท้าย:

มีสองวิธีในการทำให้ชั้นเรียนเป็นขั้นสุดท้าย สิ่งแรกคือการใช้คำสำคัญสุดท้ายในการประกาศคลาส:

public final class SomeClass {
  //  . . . Class contents
}

วิธีที่สองในการทำให้คลาสสุดท้ายคือประกาศสิ่งก่อสร้างทั้งหมดเป็นแบบส่วนตัว:

public class SomeClass {
  public final static SOME_INSTANCE = new SomeClass(5);
  private SomeClass(final int value) {
  }

การทำเครื่องหมายเป็นขั้นสุดท้ายช่วยให้คุณประหยัดปัญหาหากพบว่าเป็นขั้นตอนสุดท้ายเพื่อแสดงให้เห็นถึงคลาสทดสอบนี้ ดูสาธารณะได้อย่างรวดเร็วก่อน

public class Test{
  private Test(Class beanClass, Class stopClass, int flags)
    throws Exception{
    //  . . . snip . . . 
  }
}

น่าเสียดายเนื่องจากคอนสตรัคเตอร์เฉพาะของคลาสนั้นเป็นแบบส่วนตัวจึงไม่สามารถขยายคลาสนี้ได้ ในกรณีของคลาสทดสอบไม่มีเหตุผลที่คลาสควรเป็นที่สิ้นสุด คลาสการทดสอบเป็นตัวอย่างที่ดีของวิธีที่คลาสสุดท้ายโดยนัยสามารถทำให้เกิดปัญหาได้

ดังนั้นคุณควรทำเครื่องหมายเป็นขั้นสุดท้ายเมื่อคุณสร้างคลาสโดยปริยายโดยทำให้เป็นคอนสตรัคเตอร์ส่วนตัว


4

คลาสสุดท้ายคือคลาสที่ไม่สามารถขยายได้ นอกจากนี้ยังสามารถประกาศวิธีการเป็นขั้นสุดท้ายเพื่อระบุว่าไม่สามารถเขียนทับด้วยคลาสย่อย

การป้องกันไม่ให้คลาสย่อยมีประโยชน์อย่างยิ่งหากคุณเขียน APIs หรือไลบรารีและต้องการหลีกเลี่ยงการขยายเพื่อแก้ไขพฤติกรรมพื้นฐาน


4

ข้อดีอย่างหนึ่งของการทำให้ชั้นเรียนเป็นขั้นสุดท้าย: -

คลาสสตริงถูกเก็บรักษาไว้เป็นลำดับสุดท้ายดังนั้นจึงไม่มีใครสามารถแทนที่วิธีการและเปลี่ยนการทำงานได้ เช่นไม่มีใครสามารถเปลี่ยนการทำงานของความยาว () วิธีการ มันจะส่งคืนความยาวของสตริงเสมอ

นักพัฒนาของคลาสนี้ไม่ต้องการให้ใครเปลี่ยนฟังก์ชั่นของคลาสนี้ดังนั้นเขาจึงถือเป็นที่สุด


3

ใช่บางครั้งคุณอาจต้องการสิ่งนี้ด้วยเหตุผลด้านความปลอดภัยหรือความเร็ว มันทำใน C ++ เช่นกัน มันอาจจะไม่ได้เป็นที่บังคับสำหรับโปรแกรม แต่ moreso สำหรับกรอบ http://www.glenmccl.com/perfj_025.htm


3

ในคำหลักสุดท้าย Java ใช้สำหรับโอกาสด้านล่าง

  1. ตัวแปรสุดท้าย
  2. วิธีการขั้นสุดท้าย
  3. ชั้นเรียนสุดท้าย

ในตัวแปรสุดท้ายของ Java ไม่สามารถกำหนดใหม่คลาสสุดท้ายไม่สามารถขยายได้และวิธีการสุดท้ายจะไม่สามารถแทนที่ได้


1

คลาสสุดท้ายไม่สามารถขยายได้ ดังนั้นหากคุณต้องการให้คลาสทำงานในลักษณะที่แน่นอนและไม่มีใครแทนที่วิธีการ (ด้วยรหัสที่มีประสิทธิภาพน้อยกว่าและเป็นอันตรายมากกว่า) คุณสามารถประกาศคลาสทั้งหมดเป็นวิธีสุดท้ายหรือวิธีเฉพาะที่คุณไม่ต้องการ การเปลี่ยนแปลง

เนื่องจากการประกาศคลาสไม่ได้ป้องกันคลาสจากอินสแตนซ์มันไม่ได้หมายความว่ามันจะหยุดคลาสจากการมีคุณสมบัติของวัตถุ มันเป็นเพียงแค่ว่าคุณจะต้องติดกับวิธีการเพียงวิธีที่พวกเขาจะประกาศในชั้นเรียน


1

คิดว่า FINAL เป็น "End of the line" - ผู้ชายคนนั้นไม่สามารถผลิตลูกหลานได้อีกต่อไป ดังนั้นเมื่อคุณเห็นด้วยวิธีนี้มีสถานการณ์จำลองมากมายที่คุณจะเจอที่ต้องให้คุณติดธงเครื่องหมาย 'สิ้นสุดบรรทัด' ลงในชั้นเรียน มันคือการออกแบบที่ขับเคลื่อนด้วยโดเมน - ถ้าโดเมนของคุณต้องการให้ ENTITY ที่กำหนด (คลาส) ไม่สามารถสร้างคลาสย่อยได้ให้ทำเครื่องหมายเป็น FINAL

ฉันควรทราบว่าไม่มีสิ่งใดหยุดคุณจากการสืบทอดคลาส "ควรถูกแท็กเป็นขั้นสุดท้าย" แต่โดยทั่วไปแล้วจะจัดอยู่ในประเภท "การละเมิดมรดก" และทำเพราะส่วนใหญ่คุณต้องการรับฟังก์ชั่นบางอย่างจากคลาสฐานในคลาสของคุณ

วิธีที่ดีที่สุดคือการดูโดเมนและให้มันกำหนดการออกแบบของคุณ


1

ดังที่ได้กล่าวไว้ข้างต้นหากคุณต้องการไม่มีใครสามารถเปลี่ยนการทำงานของวิธีการได้จากนั้นคุณสามารถประกาศเป็นขั้นสุดท้าย

ตัวอย่าง: พา ธ ของไฟล์เซิร์ฟเวอร์แอปพลิเคชันสำหรับดาวน์โหลด / อัพโหลดแยกสตริงตามออฟเซ็ตวิธีการดังกล่าวที่คุณสามารถประกาศได้เป็นครั้งสุดท้ายเพื่อให้ฟังก์ชันของวิธีการเหล่านี้จะไม่ถูกเปลี่ยนแปลง และถ้าคุณต้องการวิธีสุดท้ายในชั้นเรียนแยกต่างหากให้กำหนดคลาสนั้นเป็นคลาสสุดท้าย ดังนั้นชั้นเรียนสุดท้ายจะมีวิธีสุดท้ายทั้งหมดซึ่งเป็นวิธีสุดท้ายที่สามารถประกาศและกำหนดไว้ในชั้นเรียนที่ไม่ใช่ครั้งสุดท้าย


1

คลาส Android Looper เป็นตัวอย่างที่ดีสำหรับเรื่องนี้ http://developer.android.com/reference/android/os/Looper.html

คลาส Looper จัดเตรียมฟังก์ชันการทำงานบางอย่างซึ่งไม่ได้มีวัตถุประสงค์เพื่อแทนที่โดยคลาสอื่น ๆ ดังนั้นไม่มีคลาสย่อยที่นี่


1

สมมติว่าคุณมีชั้นเรียนที่มีวิธีการEmployee greetเมื่อวิธีการที่เรียกว่ามันก็พิมพ์greet Hello everyone!นั่นคือพฤติกรรมที่คาดหวังของgreetวิธีการ

public class Employee {

    void greet() {
        System.out.println("Hello everyone!");
    }
}

ตอนนี้ให้GrumpyEmployeesubclass Employeeและgreetวิธีการแทนที่ดังแสดงด้านล่าง

public class GrumpyEmployee extends Employee {

    @Override
    void greet() {
        System.out.println("Get lost!");
    }
}

ตอนนี้ในรหัสด้านล่างได้ดูsayHelloวิธีการ มันต้องใช้เวลาEmployeeเช่นเป็นพารามิเตอร์และเรียกวิธีการทักทายหวังว่ามันจะพูดแต่สิ่งที่เราได้รับคือHello everyone! Get lost!การเปลี่ยนแปลงพฤติกรรมนี้เป็นเพราะEmployee grumpyEmployee = new GrumpyEmployee();

public class TestFinal {
    static Employee grumpyEmployee = new GrumpyEmployee();

    public static void main(String[] args) {
        TestFinal testFinal = new TestFinal();
        testFinal.sayHello(grumpyEmployee);
    }

    private void sayHello(Employee employee) {
        employee.greet(); //Here you would expect a warm greeting, but what you get is "Get lost!"
    }
}

สถานการณ์นี้สามารถหลีกเลี่ยงได้ถ้าระดับที่ถูกสร้างขึ้นEmployee finalแค่คิดจำนวนของความสับสนวุ่นวายโปรแกรมเมอร์หน้าด้านอาจก่อให้เกิดถ้าชั้นไม่ได้ถูกประกาศให้เป็นStringfinal


1

ชั้นเรียนสุดท้ายไม่สามารถขยายเพิ่มเติมได้ ถ้าเราไม่จำเป็นต้องสร้างคลาสที่สืบทอดได้ใน java เราสามารถใช้วิธีนี้

หากเราเพียงแค่ต้องทำวิธีการเฉพาะในชั้นเรียนเพื่อไม่ให้ถูกแทนที่เราก็สามารถใส่คำหลักสุดท้ายต่อหน้าพวกเขา ชั้นนั้นยังคงสืบทอดอยู่


-1

การวางแนววัตถุไม่ได้เกี่ยวกับการสืบทอด แต่มันเกี่ยวกับการห่อหุ้ม และมรดกแบ่งออกจากแค็ปซูล

การประกาศคลาสสุดท้ายทำให้มีความสมบูรณ์ในหลายกรณี วัตถุใด ๆ ที่แสดง“ มูลค่า” เช่นสีหรือจำนวนเงินอาจถือเป็นที่สิ้นสุด พวกเขายืนด้วยตัวเอง

หากคุณกำลังเขียนไลบรารีให้ชั้นเรียนของคุณเป็นขั้นสุดท้ายเว้นแต่ว่าคุณได้เยื้องพวกเขาอย่างชัดเจน มิฉะนั้นผู้คนอาจได้รับคลาสและวิธีการแทนที่ของคุณทำลายสมมติฐาน / ค่าคงที่ของคุณ นี่อาจมีผลกระทบด้านความปลอดภัยเช่นกัน

Joshua Bloch ใน“ Effective Java” แนะนำให้ออกแบบอย่างชัดเจนสำหรับการสืบทอดหรือห้ามมันและเขาสังเกตว่าการออกแบบเพื่อการสืบทอดไม่ใช่เรื่องง่าย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.