อะไรคือความแตกต่างระหว่างคำนำหน้าชื่อ“ กับ” และ“ เป็น” ความแตกต่าง? [ปิด]


78

ความแตกต่างระหว่าง"กับ"และ"เป็น"คำนำหน้าชื่อเมธอดเช่นคืออะไร

  • ToList ()
  • asList ()
  • ฯลฯ ...

เมื่อใดที่จะใช้ซึ่งเมื่อออกแบบวิธีการ?

คำตอบ:


120

toXYZ()ฟังก์ชั่นที่คาดว่าจะทำแปลงและจะกลับมาใหม่เป็นอิสระวัตถุ ( แต่เปลี่ยนไม่ได้ช่วยให้การเพิ่มประสิทธิภาพjava.lang.String.toString()เพียงแค่ส่งกลับวัตถุ)
ตัวอย่างเช่นใน C ++ เรามีstd::bitset::to_ulong()สิ่งที่สามารถล้มเหลวได้อย่างง่ายดายและมีto_string()การแปลงที่ซับซ้อน (มากหรือน้อย) ทั้งหมดและทำการจัดสรรหน่วยความจำ

asXYZ()ฟังก์ชั่นบนมืออื่น ๆ ที่คาดว่าจะกลับมาเป็น (ที่แตกต่างกันอาจ) มุมมองของแหล่งที่มาของการทำงานน้อยที่สุด
ตัวอย่างเช่นใน C ++ เรามีstd::as_const()เพียงแค่คืนค่าอ้างอิงคงที่และยิ่งเกี่ยวข้องstd::forward_as_tupleซึ่งอ้างอิงถึงการขัดแย้งโดยอ้างอิง


19
ปรากฎว่ามีบางอย่างที่มีอยู่ก่อนหน้านี้ โดยทั่วไปแล้ว [บางสิ่ง] จะคล้ายกับตัวละครในขณะที่ [บางสิ่ง] สร้างวัตถุใหม่ (ที่มีประเภทแตกต่างกัน) จากวัตถุที่มีอยู่เดิม ในกรณีของ ToList มันจะเป็น O (n) และเกือบจะแพงกว่า "As" อย่างแน่นอน ดู stackoverflow.com/questions/17968469/…
Robert Harvey

5
มันเป็นส่วนหนึ่งของการเลือกชื่อที่สื่อความหมายและแม้ว่าความแตกต่างเฉพาะนี้ไม่ได้ทำเป็นมาตรฐานการเข้ารหัสละเมิดมันแบ่งหลักการน้อยมหัศจรรย์
Deduplicator

11
ฉันจะอธิบายมันโดยสัญชาตญาณฉันคิดว่า "เป็น" เป็น "เปลี่ยนเป็น" และ "เป็น" เป็น "ถือว่าเป็น" อดีตหมายถึงงานเพื่อเปลี่ยนแปลงสิ่งหลังหมายถึงมันเป็นเพียงความแตกต่างในวิธีที่คุณทำงานกับมัน
Latty

6
ถ้ามันหมายถึงบางสิ่งมันก็ควรจะหมายถึงสิ่งนี้ ฉันขอแนะนำว่าบ่อยครั้งที่มันไม่ได้มีความหมายอะไรเลยดังนั้นฉันจะไม่พึ่งพามันในรหัสของบุคคลที่สามแบบสุ่ม (โดยไม่เห็นบางอย่างในเอกสาร) มันจะเป็นการดีที่จะนำมาใช้ในฐานรหัส
Ben

4
คำตอบนี้ยังแม่นยำใน C ++: ตัวอย่างเช่นstd::to_string(x)สร้างวัตถุสตริงใหม่ แต่std::as_const(x)สร้างการอ้างอิง (มุมมอง) ของวัตถุที่มีอยู่
Quuxplusone

13

สุจริตอาจเป็นเพียงการตั้งชื่อที่ไม่สอดคล้องกัน หากมองไปที่วัตถุห้องสมุดมาตรฐานในสมอลล์ทอล์คเช่นวิธีการทั้งหมดที่ทำ "แปลงซับซ้อน" หรือ "กลับมาแสดงที่เรียบง่ายในรูปแบบอื่น" จะมีคำนำหน้าasเช่นเดียวกับในasString, asFloat, และวิธีการมาตรฐานสำหรับการแปลงอะไรเพื่ออะไรอื่นasSecondsas: aClass

ในทับทิมชนิดเดียวกันของวิธีการจะมีคำนำหน้าto_เช่นเดียวกับในto_s, to_a, to_hสั้นstring, arrayและhashตามลำดับ

ทั้งห้องสมุดมาตรฐานดูเหมือนจะแยกความแตกต่างระหว่างการแปลงประเภทต่าง ๆ อาจเป็นเพราะมันควรจะถือเป็นรายละเอียดการใช้งาน

อย่างไรก็ตามในชวาเราเห็นการปะปนกันมากมาย ในขณะที่คุณกล่าวถึงมีtoString, asListและอื่น ๆ ฉันเชื่อว่าสิ่งเหล่านี้เป็นเพียงการตั้งชื่อที่ไม่สอดคล้องกันเพราะถ้าคุณพยายามกำหนดความหมายที่แตกต่างกันไปในแต่ละคำนำหน้าคุณจะพบตัวอย่างตัวนับที่อื่นในไลบรารีมาตรฐานเสมอ

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


1
ฉันไม่เชื่อ: เลือกสไตล์เดียวให้กับทั้งทีมแทนที่จะเลือกสไตล์เดียวสำหรับเคสที่คล้ายกันในโมดูล
Daniel Hári

12
ใน Java toStringสร้างสายใหม่ตัดการเชื่อมต่ออย่างสมบูรณ์จากวัตถุ (และไม่มีวิธีอื่นเนื่องจากความไม่สามารถเปลี่ยนได้) การเก็บเช่นเดียวกันสำหรับCollection#toArrayในขณะที่Arrays#asListส่งกลับมุมมองของอาเรย์ซึ่งเชื่อมต่อแบบสองทิศทาง (การกลายพันธุ์อาเรย์เปลี่ยนรายการและในทางกลับกัน) ดังนั้นจึงค่อนข้างสม่ำเสมอแม้ว่าอาจมีข้อยกเว้น เลือกหนึ่งคำนำหน้าจะผิด หากมีอยู่Arrays#toListฉันก็คาดหวังให้สร้างรายการใหม่ด้วยอาร์เรย์อ้างอิงใหม่
maaartinus

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

3
@usr Smalltalk อาจได้รับการออกแบบก่อนที่จะกลายเป็นแบบแผน
Bergi

6

ในขณะที่มีอยู่แล้วคำตอบที่ได้รับการยอมรับก็ดูเหมือนว่าจะมุ่งเน้นไปที่ C ++ ในขณะที่คำถามที่ติดแท็กด้วยJava ใน Java ตัวอย่างแรกที่คำนึงถึงสิ่งนี้คือArrays.asListซึ่งส่งคืนมุมมองของอาร์เรย์เป็นหลักซึ่งห่อหุ้มอยู่ในรายการ อาเรย์พื้นฐานและรายการยังคงเชื่อมต่ออยู่ การเปลี่ยนแปลงในอาร์เรย์จะมีผลในรายการและในทางกลับกัน อย่างไรก็ตามอาร์เรย์ที่ส่งคืนโดยเมธอดtoArrayของรายการนั้นไม่ขึ้นอยู่กับอาร์เรย์ดั้งเดิมและจากรายการ:

String[] wordArray = {"one", "fine", "day"};
List<String> wordList = Arrays.asList(wordArray);

// changes to the array are visible in the list
System.out.println(wordList); // prints "[one, fine, day]"
wordArray[1] = "horrible";
System.out.println(wordList); // prints "[one, horrible, day]"

// changes to the list are visible in the array
wordList.set(1, "beautiful");
System.out.println(wordArray[1]); // prints "beautiful"

// but changes to the list or array don't affect the 
// result from the list's toArray method.
String[] moreWords = wordList.toArray(new String[] {});
wordList.set(0, "the");
wordArray[1] = "best";
for (int i=0; i<3; i++) {
  System.out.println(moreWords[i]); // prints "one", "beautiful", and "day"
}

ทั้งหมดที่กล่าวมาไม่มีการรับประกันว่านักพัฒนาห้องสมุดทุกคนจะปฏิบัติตามอนุสัญญานี้ดังนั้นคุณยังต้องตรวจสอบเอกสารเพื่อดูว่านี่เป็นพฤติกรรมที่คุณจะได้รับจากรหัสที่ไม่รู้จักหรือไม่

สถานที่อื่น ๆ ที่ฉันเคยเห็นว่าเป็น ... ()วิธีการที่ใช้บ่อยอยู่ในประเภท downcasting เป็นประเภทย่อย เช่นหากคุณมีชุดย่อยที่ระบุคุณอาจท้ายด้วยรหัสเช่น:

  /**
   * Every Node is either an ANode or a BNode.
   */
  interface Node {

    /**
     * Returns this Node as an ANode.
     * 
     * @return this node
     */
    default ANode asANode() {
      if (this instanceof ANode) {
        return (ANode) this;
      }
      else {
        throw new UnsupportedOperationException();
      }
      // Or, in Java8 style, perhaps:
      // return Optional.of(this)
      //     .filter(ANode.class::isInstance)
      //     .map(ANode.class::cast)
      //     .orElseThrow(UnsupportedOperationException::new);
    }

    /**
     * Returns this Node as a BNode.
     * 
     * @return this node
     */
    default BNode asBNode() {
      if (this instanceof BNode) {
        return (BNode) this;
      }
      else {
        throw new UnsupportedOperationException();
      }
    }
  }

1

ความแตกต่างที่ฉันสังเกตุ (ตอนนี้กำลังคิดถึงมัน) คือ

  • โดยทั่วไปแล้วจะแปลงเป็นประเภทการอ้างอิงที่แตกต่างกัน (วัตถุที่ค่อนข้างซับซ้อน)
  • ตามปกติแล้วจะส่งคืนประเภทค่าอย่างง่าย

ดังนั้นเราจึงเห็น AsInteger และ AsString และเราเห็น ToArray และ ToStringList

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

วิธีการค้นหาอีกครั้งที่นี่:

  • To เป็นการดำเนินการดังนั้นคุณจะใช้มันสำหรับวิธีการ
  • ในฐานะที่เป็นตัวแทนง่ายดังนั้นคุณจะใช้มันสำหรับคุณสมบัติ

จากนั้นก็มี "ศิลปะก่อน" (หรือมรดก) เพื่อจัดการกับ ก่อนที่ภาษาจะมี OO อย่างสมบูรณ์ตั้งแต่เริ่มต้นคุณจะมีฟังก์ชั่นห้องสมุดเช่น StrToInt () และ IntToStr () พวกเขาทำการแปลงพวกเขากำลังดำเนินการดังนั้นจึงเหมาะสมที่จะเรียกพวกเขาว่า SomethingToSomethingelse () หลังจากทั้งหมด To มีการใช้งานมากกว่าเป็น ฉันกำลังคิดเกี่ยวกับ Delphi โดยเฉพาะอย่างยิ่งที่นี่

เมื่อ C # ได้รับการออกแบบโดยมีความทะเยอทะยานที่จะไป OO ตลอดทางมันสมเหตุสมผลที่จะมีวิธีการในวัตถุจำนวนเต็มในขณะนี้ที่จะแปลงจำนวนเต็มเป็นสตริง แม้ว่าเราจะมีคลาส Convert แต่การแปลงเป็นสตริงนั้นเป็นเรื่องธรรมดามากที่มันถูกสร้างเป็นวิธีเสมือนบนวัตถุ ผู้ออกแบบอาจจะคิดว่า ToString น่าจะคุ้นเคยกับผู้คนจากกระบวนทัศน์เก่าและบางทีนี่อาจเป็นเหตุผลว่าทำไมเราถึงได้ใช้วิธีเสมือน ToString () และไม่ใช่ AsString อสังหาริมทรัพย์เสมือน


3
เกี่ยวกับtoString()อะไร
Deduplicator

คุณมาถึงฉันแล้ว ฉันคิดว่า AsString น่าจะเหมาะสมกว่า ฉันมีความคิดเพิ่มเติมฉันจะอัปเดตคำตอบของฉัน
Martin Maat

ฉันไม่คิดว่าคำตอบนี้จะจัดทำอนุสัญญาใน C # จริงๆ เช่น. ToList () และ AsEnumerable () ทั้งคืนค่าวัตถุที่ซับซ้อนความแตกต่างคือ ToList () ส่งคืนวัตถุใหม่เสมอในขณะที่ AsEnumerable () ส่งคืนมุมมองหรืออแด็ปเตอร์เหนือวัตถุต้นฉบับ
JacquesB

@JaquesB เห็นได้ชัดว่าความคิดที่แตกต่างได้ถูกนำมาใช้ที่นี่และที่นั่น Delphi มีคุณสมบัติ AsInteger และ AsString บนวัตถุ TField (ซึ่งห่อหุ้มฟิลด์ฐานข้อมูล) ฉันอาจจะลำเอียงโดยสิ่งนี้ แต่อีกครั้งคำถามถูกแท็กด้วย Java ไม่ใช่กับ C # หรือ Delphi
Martin Maat
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.