มันเป็นการปฏิบัติที่ไม่ถูกต้องหรือไม่ที่จะทำให้สุนัขเซทเทอร์กลับมา“ สิ่งนี้”?


249

เป็นความคิดที่ดีหรือไม่ดีที่จะทำให้ setters ใน java คืนค่า "this" หรือไม่?

public Employee setName(String name){
   this.name = name;
   return this;
}

รูปแบบนี้มีประโยชน์เพราะจากนั้นคุณสามารถโยงผู้ตั้งค่าเช่นนี้:

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

แทนสิ่งนี้:

Employee e = new Employee();
e.setName("Jack Sparrow");
...and so on...
list.add(e);

... แต่มันขัดแย้งกับการประชุมมาตรฐาน ฉันคิดว่ามันอาจจะคุ้มค่าเพียงเพราะมันทำให้สุนัขตัวนั้นทำสิ่งอื่นที่มีประโยชน์ ฉันเคยเห็นรูปแบบนี้ใช้สถานที่บางแห่ง (เช่น JMock, JPA) แต่ดูเหมือนว่าผิดปกติและใช้โดยทั่วไปสำหรับ API ที่กำหนดไว้อย่างดีเท่านั้นซึ่งรูปแบบนี้มีการใช้ทุกที่

ปรับปรุง:

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


1
เมื่อฉันเห็นรูปแบบการออกแบบนี้เมื่อไม่นานมานี้ thisหากวิธีการที่ไม่จำเป็นอย่างชัดเจนที่จะกลับสิ่งที่จะทำในงานของตนตอนนี้ก็ผลตอบแทน บางครั้งฉันก็เปลี่ยนฟังก์ชั่นเพื่อที่แทนที่จะส่งกลับค่ามันทำงานกับสมาชิกของวัตถุเพียงเพื่อให้ฉันสามารถทำได้ มันวิเศษมาก :)
Inversus

4
สำหรับตัวตั้งค่าแบบ telescopic ที่ส่งคืนตัวเองและในตัวสร้างฉันต้องการใช้ withName (ชื่อ String) แทน setName (ชื่อ String) ในขณะที่คุณชี้ให้เห็นถึงการปฏิบัติทั่วไปและความคาดหวังสำหรับผู้ตั้งค่าคือการคืนค่าเป็นโมฆะ setters "ที่ไม่ได้มาตรฐาน" อาจทำงานได้ไม่ดีกับเฟรมเวิร์กที่มีอยู่เช่นตัวจัดการเอนทิตี JPA, Spring เป็นต้น
oᴉɹǝɥɔ

โปรดแนะนำตัวแบ่งบรรทัดก่อนที่จะทำการร้องขอแต่ละครั้ง :) และกำหนดค่า IDE ของคุณหรือรับค่าที่เหมาะสมหากไม่เป็นไปตามนี้
MauganRa

เฟรมเวิร์กที่ใช้กันอย่างแพร่หลาย (เช่น Spring และ Hibernate) จะเคร่งครัด (อย่างน้อยพวกเขาเคย) ปฏิบัติตามอนุสัญญาโมฆะ - ผู้ตั้งถิ่นฐาน
Legna

คำตอบ:


83

ฉันไม่คิดว่าจะมีอะไรผิดปกติกับมันเป็นเรื่องของสไตล์ มันมีประโยชน์เมื่อ:

  • คุณต้องตั้งค่าหลายฟิลด์ในครั้งเดียว (รวมถึงที่การก่อสร้าง)
  • คุณรู้ว่าต้องตั้งค่าฟิลด์ใดในเวลาที่คุณเขียนโค้ดและ
  • มีชุดค่าผสมหลายชุดที่คุณต้องการตั้งค่าฟิลด์

ทางเลือกสำหรับวิธีนี้อาจเป็น:

  1. ตัวสร้างเมกะหนึ่ง (ข้อเสีย: คุณอาจผ่านค่า null หรือค่าเริ่มต้นจำนวนมากและยากที่จะทราบว่าค่าใดสอดคล้องกับค่าใด)
  2. คอนสตรัคเตอร์ที่โอเวอร์โหลดหลายตัว (ข้อเสีย: แย่ลงเมื่อคุณมีมากกว่าสองสาม)
  3. วิธีการแบบโรงงาน / แบบคงที่ (ข้อเสีย: เช่นเดียวกับตัวสร้างที่มากเกินไป - จะเทอะทะเมื่อมีมากกว่าสองสามครั้ง)

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


1
โดยทั่วไปแล้วคุณจะไม่ส่งคืนสิ่งใดจากผู้ตั้งค่าด้วยการประชุม
Ken Liu

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

12
@Tom จุดที่ดีการทำเช่นนี้แบ่งการประชุม "Java bean" สำหรับ getters และ setters
Andy White

2
@TomClift การทำลายการประชุม "Java Bean" ทำให้เกิดปัญหาใด ๆ หรือไม่ ไลบรารีที่ใช้หลักการ "Java Bean" ดูประเภทการคืนค่าหรือเพียงแค่พารามิเตอร์เมธอดและชื่อเมธอด
Theo Briscoe

3
นั่นคือเหตุผลที่รูปแบบการสร้างที่มีอยู่ setters ไม่ควรกลับมาบางสิ่งบางอย่างแทนที่จะสร้างสร้างถ้ารูปลักษณ์ที่จำเป็นดีกว่าและใช้เวลาน้อยรหัส :)
RicardoE

106

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

สิ่งนี้เรียกว่าลวดลายตัวสร้างหรือส่วนต่อประสานที่คล่องแคล่วอินเตอร์เฟซได้อย่างคล่องแคล่ว

เป็นเรื่องปกติใน Java API:

String s = new StringBuilder().append("testing ").append(1)
  .append(" 2 ").append(3).toString();

26
มันมักใช้ในผู้สร้าง แต่ฉันจะไม่พูดว่า "นี่คือ ... เรียกว่ารูปแบบตัวสร้าง"
ลอเรนซ์ Gonsalves

10
มันตลกสำหรับฉันที่เหตุผลบางประการสำหรับอินเทอร์เฟซที่คล่องแคล่วคือพวกมันทำให้การอ่านโค้ดง่ายขึ้น ฉันเห็นว่าการเขียนสะดวกกว่า แต่ก็ทำให้ฉันรู้สึกว่าอ่านยากขึ้น นั่นเป็นความขัดแย้งที่แท้จริงเพียงอย่างเดียวที่ฉันมี
Brent Writes Code

30
มันยังเป็นที่รู้จักกันในนาม Antipattern ซากรถไฟ ปัญหาคือเมื่อการติดตามสแต็กข้อยกเว้น null - พอยน์ไลน์ประกอบด้วยบรรทัดเช่นนี้คุณไม่มีความคิดว่าการร้องขอคืนค่า null ไม่ได้หมายความว่าควรหลีกเลี่ยงการผูกมัด แต่ต้องระวังห้องสมุดที่ไม่ดี (โดยเฉพาะ home-Brewn)
ddimitrov

18
@ddimitrov ตราบใดที่คุณ จำกัด ให้ส่งคืนสิ่งนี้จะไม่มีปัญหา (เฉพาะการเชิญครั้งแรกเท่านั้นที่สามารถส่ง NPE)
Stefan

4
มันง่ายกว่าที่จะเขียนและอ่านเพื่อสันนิษฐานว่าคุณใส่การกระจายและการเยื้องที่การอ่านจะประสบอย่างอื่น! (เพราะมันหลีกเลี่ยงความยุ่งเหยิงซ้ำซ้อนของรหัสซ้ำเช่นbla.foo.setBar1(...) ; bla.foo.setBar2(...)เมื่อคุณสามารถเขียนbla.foo /* newline indented */.setBar1(...) /* underneath previous setter */ .setBar2(...)(ไม่สามารถใช้ linebreaks ในความคิดเห็นดังนั้นเช่นนี้ :-( ... หวังว่าคุณจะได้รับจุดพิจารณา 10 setters ดังกล่าวหรือสายที่ซับซ้อนมากขึ้น)
Andreas Dietrich

90

เพื่อสรุป:

  • มันเรียกว่า "ส่วนต่อประสานที่คล่องแคล่ว" หรือ "วิธีผูกมัด"
  • นี่ไม่ใช่ Java "มาตรฐาน" แม้ว่าคุณจะเห็นมากกว่านี้ในอีกหลายวัน (ใช้งานได้ดีใน jQuery)
  • มันละเมิดข้อกำหนดของ JavaBean ดังนั้นมันจะแตกด้วยเครื่องมือและไลบรารีต่าง ๆ โดยเฉพาะอย่างยิ่งผู้สร้าง JSP และ Spring
  • มันอาจป้องกันการเพิ่มประสิทธิภาพบางอย่างที่ JVM ปกติจะทำ
  • บางคนคิดว่าทำความสะอาดรหัสขึ้นบางคนคิดว่ามัน "น่ากลัว"

อีกสองประเด็นที่ไม่ได้กล่าวถึง:

  • นี่เป็นการละเมิดหลักการที่แต่ละฟังก์ชั่นควรทำอย่างใดอย่างหนึ่ง คุณอาจจะหรืออาจไม่เชื่อในเรื่องนี้ แต่ใน Java ฉันเชื่อว่ามันทำงานได้ดี

  • IDE จะไม่สร้างสิ่งเหล่านี้ให้คุณ (โดยค่าเริ่มต้น)

  • ในที่สุดฉันก็เป็นจุดข้อมูลจริง ฉันมีปัญหาในการใช้ห้องสมุดที่สร้างขึ้นเช่นนี้ ตัวสร้างแบบสอบถามของ Hibernate เป็นตัวอย่างของสิ่งนี้ในห้องสมุดที่มีอยู่ เนื่องจากเมธอด set * ของ Query ส่งคืนเคียวรีจึงเป็นไปไม่ได้ที่จะบอกเพียงแค่ดูที่ลายเซ็นวิธีใช้ ตัวอย่างเช่น:

    Query setWhatever(String what);
  • มันแนะนำความกำกวม: วิธีการแก้ไขวัตถุปัจจุบัน (รูปแบบของคุณ) หรือบางทีแบบสอบถามอาจไม่เปลี่ยนรูปแบบ (รูปแบบที่นิยมและมีคุณค่ามาก) และวิธีการนี้จะคืนค่าวัตถุใหม่ มันทำให้ไลบรารีใช้งานได้ยากขึ้นและโปรแกรมเมอร์จำนวนมากไม่ใช้คุณลักษณะนี้ หากผู้ตั้งค่าเป็นผู้ตั้งค่ามันจะชัดเจนขึ้นว่าจะใช้มันอย่างไร


5
btw คือ "คล่องแคล่ว" ไม่ใช่ "ของเหลว" ... เนื่องจากช่วยให้คุณจัดโครงสร้างชุดการเรียกใช้วิธีการเช่นภาษาพูด
Ken Liu

1
ประเด็นสุดท้ายเกี่ยวกับความไม่เปลี่ยนรูปเป็นสิ่งที่สำคัญมาก ตัวอย่างที่ง่ายที่สุดคือ String Java devs คาดหวังว่าเมื่อใช้เมธอดบน String พวกเขาจะได้รับอินสแตนซ์ใหม่ทั้งหมดและไม่ใช่อินสแตนซ์เดียวกัน แต่ได้รับการแก้ไข ด้วยส่วนต่อประสานที่คล่องแคล่วจะต้องมีการกล่าวถึงในเอกสารวิธีการว่าวัตถุที่ส่งคืนคือ 'นี้' แทนอินสแตนซ์ใหม่
MeTTeO

7
แม้ว่าฉันจะเห็นด้วยโดยรวม แต่ฉันก็ไม่เห็นด้วยว่านี่เป็นการละเมิดหลักการ "ทำเพียงสิ่งเดียว" การกลับมาthisเป็นวิทยาศาสตร์จรวดที่ซับซ้อนแทบจะไม่ :-)
user949300

จุดเพิ่มเติม: มันยังละเมิดหลักการแยกคำสั่ง - แบบสอบถาม
Marton_hun

84

ฉันชอบใช้วิธี 'กับ' สำหรับสิ่งนี้:

public String getFoo() { return foo; }
public void setFoo(String foo) { this.foo = foo; }
public Employee withFoo(String foo) {
  setFoo(foo);
  return this;
}

ดังนั้น:

list.add(new Employee().withName("Jack Sparrow")
                       .withId(1)
                       .withFoo("bacon!"));

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

list.add(new Employee().chainsetName("Jack Sparrow")
                       .chainsetId(1)
                       .chainsetFoo("bacon!"));

ด้วยอนุสัญญาการตั้งชื่อ chainsetXyz () ทุกคนควรมีความสุข


18
+1 สำหรับการประชุมที่น่าสนใจ ฉันจะไม่นำมาใช้ในรหัสของตัวเองเพราะดูเหมือนว่าตอนนี้คุณต้องมีget, setและwithสำหรับทุกชั้นเรียน มันยังคงเป็นทางออกที่น่าสนใจ :)
Paul Manta

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

2
และถ้าคุณเพิ่มรายการนี้ลงProject Lombok's @Getter/@Setterคำอธิบายประกอบ ... ที่ต้องการจะยอดเยี่ยมสำหรับการผูกมัด หรือคุณสามารถใช้บางอย่างเช่นKestrelcombinator ( github.com/raganwald/Katy ) ที่ JQuery และ Javascript ใช้
Ehtesh Choudhury

4
@ AlikElzin-kilaka จริงๆแล้วฉันเพิ่งสังเกตเห็นว่าคลาส java.time ที่ไม่เปลี่ยนรูปแบบใน Java 8 ใช้รูปแบบนี้เช่น LocalDate.withMonth, กับปี ฯลฯ
qualidafial

4
withคำนำหน้าคือการประชุมที่แตกต่างกัน ตามที่ @qualidafial ได้ยกตัวอย่าง เมธอดที่นำหน้าด้วยwithไม่ควรส่งคืนthisแต่เป็นอินสแตนซ์ใหม่เช่นอินสแตนซ์ปัจจุบัน แต่withเปลี่ยนไป สิ่งนี้ทำเมื่อคุณต้องการให้วัตถุของคุณไม่เปลี่ยนรูป ดังนั้นเมื่อฉันเห็นวิธีนำหน้าด้วยwithฉันถือว่าฉันจะได้รับวัตถุใหม่ไม่ใช่วัตถุเดียวกัน
tempcke

26

หากคุณไม่ต้องการกลับ'this'จาก setter แต่ไม่ต้องการใช้ตัวเลือกที่สองคุณสามารถใช้ไวยากรณ์ต่อไปนี้เพื่อตั้งค่าคุณสมบัติ:

list.add(new Employee()
{{
    setName("Jack Sparrow");
    setId(1);
    setFoo("bacon!");
}});

นอกจากนี้ฉันคิดว่ามันสะอาดกว่าเล็กน้อยใน C #:

list.Add(new Employee() {
    Name = "Jack Sparrow",
    Id = 1,
    Foo = "bacon!"
});

16
วงเล็บปีกกาเริ่มต้นสองครั้งอาจมีปัญหากับเท่ากับเพราะมันสร้างชั้นในที่ไม่ระบุชื่อ; ดูc2.com/cgi/wiki?DoubleBraceInitialization
Csaba_H

@Csaba_H เห็นได้ชัดว่าปัญหาคือความผิดของคนที่ทำผิดequalsวิธี มีวิธีที่สะอาดมากในการจัดการกับคลาสที่ไม่ระบุชื่อequalsหากคุณรู้ว่าคุณกำลังทำอะไรอยู่
AJMansfield

สร้างคลาสใหม่ (ไม่ระบุชื่อ) เพื่อสิ่งนั้นใช่ไหม สำหรับทุกตัวอย่าง?
user85421

11

ไม่เพียง แต่ทำลายการประชุมของ getters / setters แต่ยังทำลายกรอบการอ้างอิงเมธอด Java 8 MyClass::setMyValueเป็นBiConsumer<MyClass,MyValue>และเป็นmyInstance::setMyValue Consumer<MyValue>หากคุณมี setter ของคุณกลับมาแสดงthisว่ามันไม่ใช่อินสแตนซ์ที่ถูกต้องอีกต่อไปConsumer<MyValue>แต่เป็น a Function<MyValue,MyClass>และจะทำให้ทุกสิ่งที่ใช้วิธีการอ้างอิงถึง setters เหล่านั้น


2
มันจะยอดเยี่ยมถ้า Java มีวิธีโอเวอร์โหลดตามประเภทการส่งคืนไม่ใช่เพียงแค่ JVM คุณสามารถหลีกเลี่ยงการเปลี่ยนแปลงที่ทำลายเหล่านี้ได้อย่างง่ายดาย
Adowrath

1
คุณสามารถกำหนดอินเตอร์เฟซที่ใช้งานได้ทั้งที่ขยายConsumer<A>และโดยการให้เริ่มต้นใช้งานFunction<A,B> void accept(A a) { apply(a); }จากนั้นสามารถใช้งานได้อย่างง่ายดายและไม่ทำลายรหัสใด ๆ ที่ต้องใช้แบบฟอร์มเฉพาะ
Steve K

โอ๊ะ! นี่เป็นเพียงความผิดธรรมดา! สิ่งนี้เรียกว่าความเข้ากันได้เป็นโมฆะ setter ที่ส่งคืนค่าสามารถทำหน้าที่เป็น Consumer ได้ ideone.com/ZIDy2M
ไมเคิล

8

ฉันไม่รู้ Java แต่ฉันทำสิ่งนี้ใน C ++ คนอื่น ๆ บอกว่ามันทำให้สายยาวมากและอ่านยากจริงๆ แต่ฉันทำมันแบบนี้หลายครั้ง:

list.add(new Employee()
    .setName("Jack Sparrow")
    .setId(1)
    .setFoo("bacon!"));

นี่จะดียิ่งขึ้น:

list.add(
    new Employee("Jack Sparrow")
    .Id(1)
    .foo("bacon!"));

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


"ดียิ่งขึ้น" ไม่สามารถใช้งานได้ดีกับฟังก์ชันการทำงานของซอร์สโค้ดรูปแบบที่มีอยู่ใน IDE รุ่นใหม่ น่าเสียดาย.
Thorbjørn Ravn Andersen

คุณน่าจะถูก ... ตัวฟอร์แมตอัตโนมัติที่ฉันใช้คือการเยื้องอัตโนมัติของ emacs
คาร์สันไมเออร์ส

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

@qualidafial คุณไม่จำเป็นต้องใช้//หลังจากแต่ละวิธีหากคุณกำหนดค่า IDE ของคุณไม่ให้เข้าร่วมบรรทัดที่ถูกห่อ (เช่น Eclipse> คุณสมบัติ> Java> สไตล์โค้ด> ฟอร์แมตเตอร์> การจัดเรียงบรรทัด> ไม่ต้องเข้าร่วมบรรทัดที่ถูกห่อแล้ว)
DJDaveMark

6

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


6

เนื่องจากมันไม่คืนค่าว่างเปล่าจึงไม่มีตัวตั้งค่าคุณสมบัติ JavaBean ที่ถูกต้องอีกต่อไป นั่นอาจสำคัญหากคุณเป็นหนึ่งในเจ็ดคนของโลกที่ใช้เครื่องมือ "Bean Builder" แบบภาพหรือหนึ่งใน 17 รายการที่ใช้องค์ประกอบ JSP-bean-setProperty


นอกจากนี้ยังสำคัญถ้าคุณใช้เฟรมเวิร์ก bean ที่รับรู้เช่น Spring
ddimitrov

6

อย่างน้อย ในทางทฤษฎีมันสามารถสร้างความเสียหายกลไกการเพิ่มประสิทธิภาพของ JVM โดยการตั้งค่าการอ้างอิงเท็จระหว่างการโทร

มันควรจะเป็นน้ำตาล syntactic แต่ในความเป็นจริงสามารถสร้างผลข้างเคียงในเครื่องเสมือนอัจฉริยะสุดยอดของ Java 43

นั่นเป็นเหตุผลที่ฉันไม่ลงคะแนนอย่าใช้มัน


10
ที่น่าสนใจ ... คุณสามารถขยายในเรื่องนี้ได้บ้างไหม?
Ken Liu

3
ลองคิดดูว่าตัวประมวลผลระดับซูเปอร์คาร์จัดการกับการประมวลผลแบบขนานได้อย่างไร วัตถุที่จะดำเนินการsetวิธีที่สองขึ้นอยู่กับsetวิธีแรกแม้ว่าจะเป็นที่รู้จักกันโดยโปรแกรมเมอร์
แมเรียน

2
ฉันยังไม่ทำตาม หากคุณตั้งค่า Foo และจากนั้น Bar ที่มีสองประโยคแยกกันวัตถุที่คุณกำลังตั้งค่า Bar จะมีสถานะที่แตกต่างจากวัตถุที่คุณตั้งค่า Foo ดังนั้นคอมไพเลอร์จึงไม่สามารถทำให้ข้อความเหล่านั้นขนานกันได้ อย่างน้อยฉันก็ไม่เห็นว่ามันจะทำได้โดยไม่ต้องแนะนำสมมติฐานที่ไม่รับประกัน (เนื่องจากฉันไม่มีความคิดเกี่ยวกับเรื่องนี้ฉันจะไม่ปฏิเสธว่าจริงๆแล้ว Java 43 ทำขนานกันในกรณีเดียว แต่ไม่ใช่ที่อื่นและแนะนำ ข้อสันนิษฐานที่ไม่มีเหตุผลในกรณีหนึ่ง แต่ไม่ใช่ข้ออื่น)
masonk

12
หากคุณไม่รู้ทดสอบ -XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining java7 jdk inlines แน่นอนวิธีการที่ถูกล่ามโซ่และทำรอบซ้ำจำนวนเดียวกันที่ใช้ในการทำเครื่องหมายเป็นโมฆะ setters เป็นร้อนและ inline พวกเขาด้วย คิดว่าคุณประเมินพลังของอัลกอริทึมการตัดแต่งกิ่งของ JVM ต่ำเกินไป หากรู้ว่าคุณกำลังคืนสิ่งนี้มันจะข้าม opcode jrs (คำสั่งส่งคืน java) และเพียงปล่อยให้มันอยู่ในสแต็ก
Ajax

1
อันเดรียฉันเห็นด้วย แต่ปัญหาปรากฏขึ้นเมื่อคุณมีเลเยอร์ตามเลเยอร์ของรหัสที่ไม่มีประสิทธิภาพ 99% ของเวลาที่คุณควรเขียนโค้ดเพื่อความชัดเจนซึ่งพูดได้มากมายที่นี่ แต่ก็มีบางครั้งที่คุณต้องสมจริงและใช้ประสบการณ์หลายปีของคุณในการปรับแต่งสถาปัตยกรรมให้ดีขึ้นก่อนเวลาอันควร
LegendLength

6

มันไม่ใช่การฝึกฝนที่ไม่ดีเลย แต่มันเข้ากันไม่ได้กับJavaBeans SpecSpec

และมีข้อกำหนดจำนวนมากขึ้นอยู่กับอุปกรณ์มาตรฐานเหล่านั้น

คุณสามารถทำให้พวกมันอยู่ร่วมกันได้ตลอดเวลา

public class Some {
    public String getValue() { // JavaBeans
        return value;
    }
    public void setValue(final String value) { // JavaBeans
        this.value = value;
    }
    public String value() { // simple
        return getValue();
    }
    public Some value(final String value) { // fluent/chaining
        setValue(value);
        return this;
    }
    private String value;
}

ตอนนี้เราสามารถใช้พวกเขาร่วมกัน

new Some().value("some").getValue();

นี่คืออีกเวอร์ชั่นสำหรับวัตถุที่ไม่เปลี่ยนรูปแบบ

public class Some {

    public static class Builder {

        public Some build() { return new Some(value); }

        public Builder value(final String value) {
            this.value = value;
            return this;
        }

        private String value;
    }

    private Some(final String value) {
        super();
        this.value = value;
    }

    public String getValue() { return value; }

    public String value() { return getValue();}

    private final String value;
}

ตอนนี้เราสามารถทำได้

new Some.Builder().value("value").build().getValue();

2
การแก้ไขของฉันถูกปฏิเสธ แต่ตัวอย่าง Builder ของคุณไม่ถูกต้อง ขั้นแรกให้. value () ไม่ส่งคืนสิ่งใดและไม่ได้ตั้งค่าsomeฟิลด์ ประการที่สองคุณควรเพิ่มการป้องกันและตั้งค่าsomeเป็นnullใน build () ดังนั้นจึงSomeไม่เปลี่ยนรูปอย่างแท้จริงมิฉะนั้นคุณสามารถเรียกbuilder.value()ใช้อินสแตนซ์ Builder เดียวกันได้อีกครั้ง และสุดท้ายใช่คุณมีผู้สร้าง แต่คุณSomeยังมีตัวสร้างสาธารณะหมายความว่าคุณไม่สนับสนุนการใช้ Builder อย่างเปิดเผยนั่นคือผู้ใช้ไม่ได้รู้เรื่องอื่นนอกจากลองใช้หรือค้นหาวิธีตั้งค่าแบบกำหนดเองvalueเลย
Adowrath

@Adowrath หากคำตอบนั้นไม่ถูกต้องคุณควรเขียนคำตอบของคุณเองไม่ลองและแก้ไขคนอื่นให้เป็นรูปร่าง
CalvT

1
@ JinKwon ยอดเยี่ยม ขอบคุณ! และขอโทษถ้าฉันดูหยาบก่อน
Adowrath

1
@Adowrath โปรดอย่าลังเลที่จะแสดงความคิดเห็นเพิ่มเติมสำหรับการปรับปรุง FYI ฉันไม่ใช่คนที่ปฏิเสธการแก้ไขของคุณ :)
Jin Kwon

1
ฉันรู้ว่าฉันรู้ว่า. ^^ และขอบคุณสำหรับเวอร์ชั่นใหม่ที่ตอนนี้มีตัวสร้าง "ไม่เปลี่ยนรูป - บางคน" ที่ไม่แน่นอน และมันเป็นทางออกที่ฉลาดกว่าความพยายามแก้ไขของฉันซึ่งในการเปรียบเทียบทำให้รหัสยุ่งเหยิง
Adowrath

4

ถ้าคุณใช้การประชุมเดียวกันในการสมัครทั้งหมดดูเหมือนว่าจะดี

ในทางตรงกันข้ามถ้าส่วนที่มีอยู่ของแอปพลิเคชันของคุณใช้การประชุมมาตรฐานฉันจะยึดมันและเพิ่มผู้สร้างให้กับคลาสที่ซับซ้อนมากขึ้น

public class NutritionalFacts {
    private final int sodium;
    private final int fat;
    private final int carbo;

    public int getSodium(){
        return sodium;
    }

    public int getfat(){
        return fat;
    }

    public int getCarbo(){
        return carbo;
    }

    public static class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder sodium(int s) {
            this.sodium = s;
            return this;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

        public NutritionalFacts build() {
            return new NutritionalFacts(this);
        }
    }

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}

1
นี่คือสิ่งที่รูปแบบของตัวสร้างถูกออกแบบมาเพื่อแก้ไข มันไม่ทำลาย lambdas ใน Java 8 แต่ไม่ทำลายเครื่องมือ JavaBeans ที่พิถีพิถันและจะไม่ทำให้เกิดปัญหาการปรับให้เหมาะสมใน JVM (เนื่องจากวัตถุมีอยู่ในระหว่างการสร้างอินสแตนซ์เท่านั้น) นอกจากนี้ยังแก้ปัญหา "ตัวสร้างจำนวนมากเกินไป" ที่คุณได้รับโดยไม่ใช้ตัวสร้างเช่นเดียวกับการขจัดมลพิษจากกองจากชั้นเรียนที่ไม่ระบุชื่อแบบ double-brace
ndm13

จุดที่น่าสนใจ - ฉันสังเกตเห็นว่าหากแทบไม่มีอะไรในชั้นเรียนของคุณที่ไม่เปลี่ยนรูปแบบ (เช่น GUI ที่สามารถกำหนดค่าได้สูง) คุณสามารถหลีกเลี่ยง Builder ได้ทั้งหมด
Philip Guin

4

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



3

ฉันชอบเซ็ตเทอร์ที่มี "สิ่งนี้" ส่งคืน ฉันไม่สนใจว่ามันจะไม่สอดคล้องกับถั่วหรือไม่ สำหรับฉันถ้ามันไม่เป็นไรที่จะมี "=" การแสดงออก / คำสั่งแล้ว setters ที่กลับค่าเป็นเรื่องปกติ


2

ฉันเคยชอบวิธีการนี้ แต่ฉันได้ตัดสินใจต่อต้านมัน

เหตุผล:

  • การอ่าน มันทำให้โค้ดอ่านง่ายขึ้นเพื่อให้แต่ละ setFoo () ในบรรทัดแยกต่างหาก คุณมักจะอ่านรหัสหลาย ๆ ครั้งมากกว่าครั้งเดียวที่คุณเขียน
  • ผลข้างเคียง: setFoo () ควรตั้งค่าฟิลด์ foo เท่านั้นไม่มีอะไรอื่น การย้อนกลับมานี้เป็นสิ่งพิเศษ "อะไรคือสิ่งนั้น"

รูปแบบตัวสร้างที่ฉันเห็นไม่ใช้ setFoo (foo) .setBar (bar) แบบแผน แต่มี foo (foo) .bar (bar) มากกว่า บางทีด้วยเหตุผลเหล่านั้น

มันเป็นเรื่องของรสชาติเสมอ ฉันชอบวิธีการที่ "เซอร์ไพรส์น้อยที่สุด"


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

2

รูปแบบเฉพาะนี้เรียกว่าวิธีการผูกมัด ลิงก์ Wikipediaนี้มีคำอธิบายเพิ่มเติมและตัวอย่างของการใช้ภาษาโปรแกรมต่างๆ

PS: แค่คิดถึงที่จะออกจากที่นี่เพราะฉันกำลังมองหาชื่อที่เฉพาะเจาะจง


1

ตั้งแต่แรกเห็น: "น่ากลัว!"

เมื่อคิดต่อไป

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

มีข้อผิดพลาดน้อยกว่าแนวโน้ม

Employee anEmployee = new Employee();
anEmployee.setName("xxx");
...
list.add(anEmployee);

ค่อนข้างน่าสนใจ กำลังเพิ่มแนวคิดลงใน toolbag ...


1
ไม่มันยังน่ากลัว จากมุมมองการบำรุงรักษาหลังดีกว่าเพราะง่ายต่อการอ่าน นอกจากนี้ตัวตรวจสอบโค้ดอัตโนมัติเช่น CheckStyle จะบังคับใช้บรรทัดเป็น 80 ตัวอักษรโดยค่าเริ่มต้นโค้ดจะได้รับการห่อรวมอยู่ด้วยทำให้เกิดปัญหาการอ่าน / การบำรุงรักษา และในที่สุด - มันคือ Java; ไม่มีประโยชน์ในการเขียนทุกอย่างในบรรทัดเดียวเมื่อมันจะถูกรวบรวมเป็นรหัสไบต์อย่างไรก็ตาม
OMG Ponies

1
ส่วนตัวฉันคิดว่าอดีตอ่านง่ายกว่าโดยเฉพาะถ้าคุณสร้างวัตถุหลายอย่างด้วยวิธีนี้
Ken Liu

@Ken: รหัสวิธีการ เขียนหนึ่งสำเนาในรูปแบบที่คล่องแคล่ว อีกสำเนาหนึ่งในอีกชุดหนึ่ง ตอนนี้แจกสำเนาสองชุดนี้ให้กับผู้คนสองสามคนแล้วขอให้คนที่อ่านง่ายขึ้น อ่านโค้ดเร็วขึ้น
OMG Ponies

เช่นเดียวกับเครื่องมือส่วนใหญ่มันง่ายที่จะใช้มากเกินไป JQuery มุ่งเน้นไปที่เทคนิคนี้จึงมีแนวโน้มที่จะโทรโซ่ยาวซึ่งฉันพบว่าทำให้การอ่านง่ายขึ้น
staticsan

2
มันจะไม่เป็นไรถ้ามีการแพร่กระจายต่อหน้าแต่ละจุดและเยื้อง จากนั้นจะสามารถอ่านได้เหมือนเวอร์ชันที่สอง ที่จริงแล้วมากกว่าเพราะไม่มีการซ้ำซ้อนlistในตอนแรก
MauganRa

1

ใช่ฉันคิดว่ามันเป็นความคิดที่ดี

หากฉันสามารถเพิ่มบางสิ่งได้สิ่งที่เกี่ยวกับปัญหานี้:

class People
{
    private String name;
    public People setName(String name)
    {
        this.name = name;
        return this;
    }
}

class Friend extends People
{
    private String nickName;
    public Friend setNickName(String nickName)
    {
        this.nickName = nickName;
        return this;
    }
}

สิ่งนี้จะได้ผล:

new Friend().setNickName("Bart").setName("Barthelemy");

Eclipse จะไม่ได้รับการยอมรับ! :

new Friend().setName("Barthelemy").setNickName("Bart");

นี่เป็นเพราะ setName () ส่งคืน People และไม่ใช่เพื่อนและไม่มี PeoplesetNickName

เราจะเขียน setters เพื่อส่งคืนคลาส SELF แทนชื่อคลาสได้อย่างไร?

สิ่งนี้จะเป็นเรื่องปกติ (ถ้ามีคำหลัก SELF อยู่) สิ่งนี้มีอยู่แล้วหรือไม่?

class People
{
    private String name;
    public SELF setName(String name)
    {
        this.name = name;
        return this;
    }
}

1
มีคอมไพเลอร์ Java อื่น ๆ อีกสองสามรายการนอกเหนือจาก Eclipse ที่ไม่ยอมรับ :) โดยพื้นฐานแล้วคุณกำลังเรียกใช้ fowl ของระบบประเภท Java (ซึ่งเป็นแบบสแตติกไม่ใช่แบบไดนามิกเช่นภาษาสคริปต์บางภาษา): คุณจะต้องส่งสิ่งที่มาจาก setName () ให้เพื่อนก่อนที่คุณจะสามารถ setNickName () ได้ แต่น่าเสียดายที่สำหรับลำดับชั้นการสืบทอดนี่จะเป็นการขจัดข้อได้เปรียบในการอ่านได้มากและทำให้เทคนิคที่อาจเป็นประโยชน์นี้ไม่เป็นประโยชน์
Cornel Masson

5
ใช้ยาชื่อสามัญ class Chainable <Self ขยาย Chainable> {public self doSomething () {return (Self) this;}} มันไม่ได้เป็นเทคนิคที่ปลอดภัย (มันจะคลาส cast ถ้าคุณใช้คลาสที่มีชนิด Self ที่คุณไม่สามารถเป็นกรณีได้) แต่มัน เป็นไวยากรณ์ที่ถูกต้องและคลาสย่อยจะส่งคืนประเภทของตนเอง
Ajax

นอกจากนี้: "ตัวเอง" ที่ Baptiste ใช้นี้เรียกว่าประเภทของตัวเองไม่ได้มีอยู่ในหลายภาษา (Scala เป็นคนเดียวที่ฉันคิดได้ในตอนนี้) ซึ่งการที่อาแจ็กซ์ใช้ Generics นั้นเรียกว่า "อยากรู้อยากเห็น" ที่เกิดขึ้นในรูปแบบแม่แบบ" ซึ่งพยายามที่จะรับมือกับการขาดชนิดตนเอง แต่ก็มีข้อบกพร่องบาง: (จากclass C<S extends C<S>>ซึ่งปลอดภัยกว่าธรรมดาS extends C. a) ถ้าA extends BและB extends C<B>และคุณมี A, คุณเท่านั้นที่รู้ว่า B จะถูกส่งคืนยกเว้น A จะแทนที่แต่ละวิธี ข) C<C<C<C<C<...>>>>>คุณไม่สามารถแสดงท้องถิ่นที่ไม่ใช่ดิบ
Adowrath

1

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


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

โดยปกติแล้วข้อยกเว้นจะดีกว่า แต่รหัสข้อผิดพลาดก็มีประโยชน์เช่นกันเมื่อคุณไม่สามารถใช้ข้อยกเว้นได้
Narek

1
สวัสดี @Narek บางทีคุณสามารถอธิบายรายละเอียดในกรณีที่มันควรจะใช้รหัสข้อผิดพลาดใน setters มากกว่าข้อยกเว้นและทำไม?
ddimitrov

0

จากคำสั่ง

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

ฉันเห็นสองสิ่ง

1) คำสั่งที่ไม่มีความหมาย 2) ขาดความสามารถในการอ่าน


0

สิ่งนี้อาจอ่านได้น้อย

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!")); 

หรือสิ่งนี้

list.add(new Employee()
          .setName("Jack Sparrow")
          .setId(1)
          .setFoo("bacon!")); 

วิธีนี้อ่านได้ง่ายกว่า:

Employee employee = new Employee();
employee.setName("Jack Sparrow")
employee.setId(1)
employee.setFoo("bacon!")); 
list.add(employee); 

8
ฉันคิดว่ามันอ่านง่ายถ้าคุณไม่ลองใส่รหัสทั้งหมดในบรรทัดเดียว
Ken Liu

0

ฉันได้สร้าง setters ของฉันมาระยะหนึ่งแล้วและปัญหาที่แท้จริงเพียงอย่างเดียวก็คือกับห้องสมุดที่ติดกับ getPropertyDescriptors ที่เข้มงวดเพื่อรับ bean access / ถั่วนักเขียนถั่ว ในกรณีเหล่านั้นจาวา "bean" ของคุณจะไม่มีนักเขียนที่คุณคาดหวัง

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

ในความเป็นจริงฉันกำลังพัฒนา ORM ที่มีน้ำหนักเบาของ SQL และฉันต้องเพิ่มโค้ด beyong getPropertyDescriptors ให้กับ setters ที่รู้จักซึ่งส่งคืนสิ่งนี้


0

นานมาแล้วที่คำตอบ แต่ฉันทั้งสองเซ็นต์ ... มันดี ฉันหวังว่าอินเทอร์เฟซที่คล่องแคล่วนี้ใช้บ่อยขึ้น

การทำซ้ำตัวแปร 'factory' จะไม่เพิ่มข้อมูลเพิ่มเติมด้านล่าง:

ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Foo.class);
factory.setFilter(new MethodFilter() { ...

นี่สะอาดกว่า imho:

ProxyFactory factory = new ProxyFactory()
.setSuperclass(Properties.class);
.setFilter(new MethodFilter() { ...

แน่นอนว่าเป็นหนึ่งในคำตอบที่กล่าวถึงแล้ว Java API จะต้องได้รับการปรับแต่งให้ทำอย่างถูกต้องในบางสถานการณ์เช่นการสืบทอดและเครื่องมือ


0

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

วิธีนี้ช่วยให้รหัสลูกค้าของคุณเป็น:

  • ไม่สนใจประเภทการส่งคืน
  • บำรุงรักษาง่ายกว่า
  • หลีกเลี่ยงผลข้างเคียงของคอมไพเลอร์

นี่คือตัวอย่างบางส่วน.

val employee = Employee().apply {
   name = "Jack Sparrow"
   id = 1
   foo = "bacon"
}


val employee = Employee()
with(employee) {
   name = "Jack Sparrow"
   id = 1
   foo = "bacon"
}


val employee = Employee()
employee.let {
   it.name = "Jack Sparrow"
   it.id = 1
   it.foo = "bacon"
}

0

หากฉันกำลังเขียน API ฉันจะใช้ "return this" เพื่อตั้งค่าที่จะถูกตั้งเพียงครั้งเดียว หากฉันมีค่าอื่น ๆ ที่ผู้ใช้ควรจะสามารถเปลี่ยนแปลงได้ฉันจะใช้ setter void มาตรฐานแทน

อย่างไรก็ตามมันเป็นเรื่องของการตั้งค่าและ setters ลูกโซ่จะดูค่อนข้างเย็นในความคิดของฉัน


0

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

มีวิธีอื่นในการตั้งค่าสิ่งเหล่านี้ทั้งหมดแน่นอน แต่ข้อดีที่นี่คือมันหลีกเลี่ยง 1) ตัวสร้างสาธารณะที่มีพารามิเตอร์หลายตัวและ 2) วัตถุที่ระบุบางส่วน ที่นี่คุณมีตัวสร้างรวบรวมสิ่งที่ต้องการแล้วเรียกว่า "build ()" ในตอนท้ายซึ่งสามารถมั่นใจได้ว่าวัตถุที่ระบุบางส่วนไม่ได้ถูกสร้างขึ้นเนื่องจากการดำเนินการนั้นสามารถมองเห็นได้น้อยกว่าที่สาธารณะ ทางเลือกจะเป็น "อ็อบเจกต์พารามิเตอร์" แต่ IMHO จะผลักปัญหากลับไปหนึ่งระดับ

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

ในระยะสั้นฉันคิดว่ามันเป็นการปฏิบัติที่ดีถ้าใช้อย่างถูกต้อง


-4

นิสัยที่ไม่ดี: สุนัขเซทเทอร์ตั้งตัวให้ทะเยอทะยาน

สิ่งที่เกี่ยวกับการประกาศวิธีการที่ชัดเจนสำหรับ U

setPropertyFromParams(array $hashParamList) { ... }

ไม่ดีสำหรับการเติมให้สมบูรณ์อัตโนมัติและการรีแฟคเตอร์และความสามารถในการอ่านรหัส anb สำเร็จรูป
Andreas Dietrich

เพราะ: 1) คุณต้องจำคำสั่งหรืออ่านจากเอกสาร 2) คุณหลวมความปลอดภัยประเภทเวลารวบรวมทั้งหมด 3) คุณต้องโยนค่า (นี้และ 2) แน่นอนว่าไม่ใช่ปัญหาในแบบไดนามิก ภาษาของหลักสูตร) 4) คุณสามารถไม่ขยายนี้อื่น ๆ ที่เป็นประโยชน์กว่าการตรวจสอบแถวยาวในทุกภาวนาและ 5) ถ้าคุณเปลี่ยนอะไรไม่ว่าจะสั่งซื้อหรือแม้กระทั่งการดำรงอยู่ของค่าบางอย่างที่คุณสามารถไม่ได้ตรวจสอบว่ารันไทม์ค่า มิได้รวบรวม timewithout ข้อสงสัยที่ทุกคน ด้วย setters: 1), 2), 3): ไม่เป็นปัญหา 4) การเพิ่มวิธีการใหม่ไม่ทำลายอะไรเลย 5) ข้อความผิดพลาดอย่างชัดเจน
Adowrath
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.