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


15

ฉันต้องการคืนค่า 2 ค่าจากวิธีหนึ่ง แนวทางของฉันมีดังนี้:

  1. สร้างคลาสภายในที่มี 2 ฟิลด์ที่จะใช้เพื่อรักษาค่าเหล่านั้น 2
  2. ใส่วิธีการภายในชั้นเรียนนั้น
  3. ยกตัวอย่างคลาสและเรียกใช้เมธอด

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

มันเป็นการออกแบบที่ดีและทำไม?


อีกตัวเลือกหนึ่ง (อาจจะไม่ดีหนึ่ง): BitInteger[] java.math.BigInteger.divideAndRemainder(BitInteger val)ดู มันจะส่งกลับจำนวนเต็ม 2 จำนวนเป็นค่าตอบแทนในอาร์เรย์
earlNameless

คุณต้องการส่งคืนค่าใดสองประเภท
Tulains Córdova

สำเนาซ้ำที่เป็นไปได้ - stackoverflow.com/questions/12668186/… .
m3th0dman

คำตอบ:


15

ฉันจะโต้แย้งเรื่องนี้ตามบรรทัดต่อไปนี้:

  • ทำไมเมธอดของคุณคืนค่าหลายค่า เรากำลังพูดถึงการทำงานร่วมกันชนิดใด - ค่าเหล่านั้นควรเป็นเขตข้อมูลในชั้นเรียนเดียวหรือว่าพวกเขาเพิ่งกลับมาโดยบังเอิญด้วยวิธีเดียวกัน แต่ไม่เกี่ยวข้องกัน? หากเป็นวิธีหลังคุณอาจต้องการพิจารณาแยกวิธีเป็นสองวิธีแทน แก้ไข: ใช้วิจารณญาณของคุณที่นี่; บางครั้งประเภทของการทำงานร่วมกัน "บังเอิญ" อาจเป็นตัวเลือกที่ดีที่สุด อีกตัวเลือกหนึ่งคือใช้คู่หรือสิ่งสร้าง tuple แม้ว่าใน OOP สิ่งเหล่านี้มักจะไม่ปรากฏใน API สาธารณะ (ข้อยกเว้นที่น่าสังเกตบางประการคือการรวบรวมมาตรฐาน ฯลฯ )
  • หากค่าสมควรที่จะสร้างคลาสฉันอาจจะแนะนำให้ใช้คลาสภายใน คลาสภายในมักใช้เป็นรายละเอียดการใช้งานภายในซึ่งถูกซ่อนจากภายนอก มีเหตุผลใดบ้างที่ผลลัพธ์นี้ไม่ควรเป็นคลาส "เต็มเป่า" ในสิทธิของตนเอง?
  • นอกเหนือจากการเก็บข้อมูลแล้วการปฏิบัติการใดบ้างที่ใช้กับคลาสใหม่นี้ ในการออกแบบเชิงวัตถุคุณต้องการให้พฤติกรรมที่เกี่ยวข้องอยู่ใกล้กับข้อมูลที่เกี่ยวข้อง (ซึ่งดูเหมือนว่าเป็นความตั้งใจของคุณด้วย) ควรวิธีการที่คุณอ้างถึงไม่ได้อยู่ในชั้นนี้ค่อนข้าง?

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

แก้ไข: เนื่องจาก Patkos Csaba ชี้ให้เห็นอย่างถูกต้องหลักการที่ใช้ในที่นี้คือ Single Responsibility Principle ( SRP ) - คลาสที่คุณพยายามสร้างควรมีความรับผิดชอบหนึ่งอย่าง (กำหนดเป็นเหตุผลสำหรับการเปลี่ยนแปลง ) แนวทางการออกแบบนี้จะช่วยให้คุณทราบว่าเขตข้อมูลทั้งสองของคุณอยู่ในชั้นเดียวหรือไม่ เพื่อยึดตัวอย่างวิกิพีเดียคลาสของคุณอาจถูกมองว่าเป็นรายงานประเภทหนึ่งซึ่งในกรณีนี้มันสอดคล้องกับ SRP แต่เป็นการยากที่จะแสดงความคิดเห็นโดยไม่มีข้อมูลเพิ่มเติม


ในขณะที่ฉันเห็นด้วยกับแนวคิดทั่วไปของคำตอบนี้มีกรณีที่ถูกต้องตามกฎหมายเมื่อมีการคำนวณข้อมูลที่เกี่ยวข้องอย่างใกล้ชิดสองส่วนด้วยกัน แต่ไม่มีเหตุผลใดที่จะผูกมันเข้าด้วยกัน Pair<OneClass, AnotherClass>ในกรณีดังกล่าวก็อาจจะเพียงพอที่สะอาดเพื่อกลับสิ่งที่ต้องการ บางคนจะไม่เห็นด้วย ไม่ว่าในกรณีใดPairควรมีรายละเอียดการใช้งานและไม่เคยปรากฏในวิธีสาธารณะ API
9000

@ 9000 ฉันเห็นด้วย; จริงๆแล้วฉันหมายถึงคำที่พิจารณาว่าจะต้องดำเนินการอย่างแท้จริงในกรณีนี้นั่นคือการแยกวิธีอาจไม่ใช่วิธีที่ดีที่สุดเสมอไปมันเป็นเพียงตัวบ่งชี้คร่าวๆในทิศทางนั้น ฉันจะแก้ไขตามบรรทัดเหล่านั้น
Daniel B

1
คำตอบที่ดี. สิ่งเดียวที่ฉันจะเพิ่มคือการอ้างอิงถึงหลักการความรับผิดชอบเดี่ยว (SRP) ( en.wikipedia.org/wiki/Single_responsibility_principle ) หากทำเครื่องหมายไว้อาจเป็นไปได้ว่าวิธีการสนทนาเป็นเพียงการละเมิด SRP อย่างง่ายและการแบ่งเป็นวิธีแก้ไขปัญหาที่ง่าย จากประสบการณ์ของฉันเมื่อใดก็ตามที่วิธีหนึ่งต้องการคืนค่า 2 ค่าขึ้นไปใน 90% ของกรณีมี 2 วิธีที่มีหรือควรแยกคลาสอื่น
Patkos Csaba

@PatkosCsaba ขอบคุณทำการแก้ไขเพื่อรวมไว้ ปกติฉันจะอธิบายสิ่งต่าง ๆ ในแง่ของการมีเพศสัมพันธ์และการทำงานร่วมกัน แต่ฉันเดาว่าหลักการของ SOLID นั้นถูกมองว่าเป็นกฎพื้นฐานที่จะมีชีวิตอยู่ในทุกวันนี้
Daniel B

@DanielB: ฉันเห็นว่า SOLID เป็นระดับที่สูงขึ้นและอาจเข้าใจแนวคิดได้ง่ายขึ้น การแต่งงานกันและการทำงานร่วมกันยังคงเป็นพื้นฐาน แต่พวกเขาอยู่ในระดับที่ต่ำกว่ามากขึ้น SOLID ใช้ประโยชน์อย่างมากจากการมีเพศสัมพันธ์และการทำงานร่วมกันเพื่ออธิบายหลักการและนำเสนอในระดับทั่วไปมากขึ้น
Patkos Csaba

10

มีแนวคิดของ Tuple ซึ่งให้ความสำคัญในภาษาอื่นเช่น Python

เราสามารถคืนอินสแตนซ์ของคลาสทั่วไปซึ่งง่ายต่อการใช้งานอีกครั้ง:

public class TypedTuple<L, R> implements Serializable {
private static final long serialVersionUID = 1L;

  protected L left;
  protected R right;

  protected TypedTuple() {
    // Default constructor for serialization
  }

  public TypedTuple(L inLeft, R inRight) {
    left = inLeft;
    right = inRight;
  }

  public L getLeft() {
    return left;
  }

  public R getRight() {
    return right;
  }
}

2
บางครั้งมันก็ดีที่มีวิธีคงที่ทั่วไปcreate()เพื่อหลีกเลี่ยงการต้องระบุพารามิเตอร์ประเภทในตัวสร้าง นอกจากนี้ฉันจะตั้งชื่อคลาสนี้PairแทนTupleเนื่องจากจะสามารถแสดงค่า 2 tuples เท่านั้น
สิงหาคม

5

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

สำหรับวิธีการที่ส่งกลับค่าหลายค่าฉันต้องการ

  • ส่งคืนตัวบรรจุทั่วไป (เช่นรายการหรือแผนที่) ที่มีค่าส่งคืน

หรือ

  • สร้างคลาสสำหรับค่าส่งคืนซึ่งมีเพียงฟิลด์ที่จำเป็น + getters + คอนสตรัคเตอร์ที่มีทุกฟิลด์

ตัวอย่างสำหรับตัวเลือกที่สอง:

public Class FooBarRetval {
   private String foo;
   private int bar;

   public FooBarRetval (String foo, int bar) {
      this.foo = foo;
      this.bar = bar;
   }

   public String getFoo() {
      return foo;
   }

   public int getBar() {
      return bar;
   }
}

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

ควรเลือกอันแรก
Juanin

scarfridge: ชี้ให้เห็นแล้วนำประโยคสุดท้ายออก
281377

2
เพียงใช้ฟิลด์สุดท้ายสาธารณะไม่มีเหตุผลที่จะเสียเวลากับ accessors
สิงหาคม

1

ใส่ค่าที่ส่งคืนจากหลายวิธีการในชั้นเรียนของตัวเอง / โครงสร้างมักจะใช้ในระบบข้อความตามที่มีชั้นหนึ่งสำหรับ การขอและการตอบสนอง ตัวอย่างนี้เป็น วัตถุที่เรียบง่าย Access Protocol (SOAP)

มันเป็นการออกแบบที่ดีและทำไม?

อย่างน้อยมันก็ค่อนข้างธรรมดา หากสิ่งนี้ดีหรือไม่ดีขึ้นอยู่กับกรณีพิเศษของคุณ


0

คำตอบสั้น ๆ : คุณสามารถส่งคืนอาร์เรย์หรือรายการที่มีค่าสองค่า

โดยส่วนตัวฉันจะเขียนสองวิธีที่แตกต่างเช่น

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