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


17

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

ขอบคุณ!

อัปเดต:ฉันรู้เกี่ยวกับวิธีที่หรูหรากว่าเช่นใน C #, Python, Groovy เป็นต้นฉันไม่ได้มองหาตัวอย่างเหล่านั้นโดยตรง ฉันแค่สงสัยจริงๆว่ายังมีใครบางคนอยู่ในหลุมหลบภัยพูดพึมพำว่าเขตข้อมูลสาธารณะที่ยอดเยี่ยมเป็นอย่างไรและฝูงทั้งหมดเป็นเพียงแค่แกะ ฯลฯ

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


2
พื้นฐานของคุณว่าพวกเขาเป็นข้อบกพร่องจริง ๆ ?
Aaron McIver

1
มีวิธีอื่นในการสร้างนิพจน์ค่าคงที่เชิงสัญลักษณ์ใน Java หรือไม่?
Edward Strange

@Aaron ฉันไม่ได้ระบุว่าพวกเขามีข้อบกพร่องฉันก็ระบุว่าฉันได้รับรู้ว่ามันเป็นแบบดั้งเดิมที่จุดนี้ว่าหนึ่งไม่ควรใช้เขตข้อมูลสาธารณะ การรับรู้นั้นอาจผิด แต่แน่นอนว่าเป็นสิ่งที่ฉันรับรู้
Avi Flax

@Crazy Eddie ฉันลืมเกี่ยวกับการใช้งานนั้นฉันกำลังคิดเกี่ยวกับการใช้งานทั่วไปมากขึ้นของเขตข้อมูลรัฐ ฉันจะแก้ไขคำถาม
Avi Flax

คำตอบ:


14

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

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

นี่คือการออกแบบที่ทำงานได้สำหรับpublic finalเขตข้อมูลในคลาสที่ไม่เปลี่ยนรูป

จากJava ที่มีประสิทธิภาพ :

รายการที่ 14: ในคลาสสาธารณะใช้เมธอด accessor ไม่ใช่ฟิลด์สาธารณะ

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

แม้ว่าจะไม่ใช่ความคิดที่ดีที่คลาสสาธารณะจะเปิดเผยฟิลด์โดยตรง แต่ก็เป็นอันตรายน้อยกว่าถ้าฟิลด์นั้นไม่เปลี่ยนรูป

ดูเพิ่มเติมเหตุใดฉันจึงไม่ควรใช้ POJO ที่ไม่เปลี่ยนรูปแบบแทน JavaBeans


แค่สงสัยว่าเหตุผลของคุณที่ไม่เปิดเผยใน API คืออะไร
Steven Jeuris

2
@Steven: เนื่องจากการเปิดเผยเขตข้อมูลสาธารณะคุณจะต้องเปิดเผยการนำไปใช้ หากคุณเปิดเผยเป็นgetXXX()วิธีการแทนคุณสามารถเปลี่ยนการใช้งานได้โดยไม่ต้องเปลี่ยนส่วนต่อประสาน API เช่นคุณสามารถเปลี่ยนและรับค่าจากบริการระยะไกล แต่แอปพลิเคชันที่ใช้ API นั้นไม่จำเป็นต้องรู้สิ่งนี้
Jonas

@ Jonas: โดยทั่วไปจะไม่ใช่ผู้สมัครสำหรับค่าคงที่ในตอนแรก
Steven Jeuris

@ สตีเว่น: ฉันไม่ได้พูดถึงค่าคงที่ในตอนแรก แต่จะเป็นฟิลด์สุดท้ายสาธารณะในชั้นเรียนที่ไม่เปลี่ยนรูป เช่นดูทำไมฉันไม่ควรใช้ POJO ที่ไม่เปลี่ยนรูปแบบแทน JavaBeans
Jonas

@ Jonas: เป็นกรณีการใช้ที่ดีเช่นกัน! อาจเป็นประโยชน์ในการอัปเดตคำตอบของคุณเพื่อชี้แจง
Steven Jeuris

9

การใช้คู่วิธี get / set เป็นข้อบกพร่องในการออกแบบเชิงประวัติศาสตร์ที่น่าเศร้า ฉันไม่สามารถนึกถึงภาษาอื่นที่ใช้คุณสมบัติเป็น verbosely และไร้ประสิทธิภาพ


1
ในขณะที่เป็นจริงสิ่งนี้ค่อนข้างจะตรงประเด็นของคำถามซึ่งเป็นหลักที่ให้ตัวเลือกระหว่าง set / get method และ public field มีเหตุผลอะไรที่ดีที่จะชอบฟิลด์ในบางสถานการณ์? ภาษาอื่นที่เสนอวิธีแก้ปัญหาที่ดีกว่านั้นดูเหมือนว่าจะไม่เกี่ยวข้องกับฉัน
จูลส์

5

ฉันคิดว่าเขตข้อมูลสาธารณะนั้นโอเคสำหรับชั้นเรียนที่เป็นประเภทค่าเช่นจำนวนเชิงซ้อนหรือจุดที่ชั้นทำมากกว่าประเภทดั้งเดิมของกลุ่มเล็ก ๆ น้อย ๆ ร่วมกันเช่น C-style struct และอาจกำหนดผู้ประกอบการน้อย


2
java.awt.Pointและเพื่อน ๆ ก็เป็นฝันร้าย
Tom Hawtin - tackline

@ TomHawtin-tackline: ปัญหาPointคือมันคลุมเครือไม่ว่าจะเป็นตัวแปรประเภทPointควรจะแค็ปซูลสถานที่หรือควรจะแค็ปซูลตัวตนของนิติบุคคลที่มีสถานที่ที่สามารถเปลี่ยนแปลงได้ แนวคิดผมจะถือว่าโค้ดที่ผ่านPointไปนั้นเหมือนกับโค้ดที่ผ่านอาร์เรย์
supercat

ดังนั้นถ้าฉันได้รับPointและปรับเปลี่ยนมันฉันควรคาดหวังว่าวัตถุที่อ้างถึงการปรับปรุงอย่างสมบูรณ์บนหน้าจอ? ไม่ปัญหาของPointมันคือมันไม่แน่นอน เรามีString/ StringBufferแต่ความคิดดูเหมือนจะไม่ผ่าน / ผ่านอาร์เรย์รอบมีปัญหาคล้ายกัน
Tom Hawtin - tackline

5

ในการกำหนดค่าคงที่สาธารณะมันยังคงมีประโยชน์ เช่น

int คงที่สุดท้ายสาธารณะ DAYS_IN_WEEK = 7;

อย่างไรก็ตามยังคงชอบenumมากที่สุด เช่น

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
    THURSDAY, FRIDAY, SATURDAY 
}

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

class Point
{
    public int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

แต่แล้วอีกครั้งหลายคนจะเถียงกัน structs ไม่มีสถานที่ในภาษาเช่น Java ...

1
@delnan: พวกเขาเกือบจะเหมือนกับ JavaBeans แต่ JavaBeans นั้นมีความละเอียดมากกว่าและไม่ใช่ threadsafe ดูเหตุใดฉันจึงไม่ควรใช้ POJO ที่ไม่เปลี่ยนรูปแบบแทน JavaBeans
Jonas

ข้อสังเกตเฉพาะสำหรับ Android บางอย่าง: Enums ช้ากว่าการประเมินมากกว่า ints และควรหลีกเลี่ยง นอกจากนี้ฟิลด์ที่เข้าถึงได้บ่อยโดย setters และ getters ในลูปแบบคับสามารถได้รับประโยชน์จากการเป็นแบบสาธารณะ
Nailer

2

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

ทุกวันนี้มีข้อแก้ตัวเล็กน้อยสำหรับการใช้งานเมื่อคุณสามารถสร้างคู่ getter / setter ด้วยการคลิกเมาส์


4
แต่ 10 public finalฟิลด์สามารถอ่านได้มากกว่า 10 getXXX()วิธี
Jonas

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

3
@biziclop ตามWikipedia : "แม้ว่าจะสงวนไว้เป็นคำหลักใน Java, const ไม่ได้ใช้และไม่มีฟังก์ชั่น"
Avi Flax

@Avi Flax Yeah แต่มันอาจถูกใช้เพื่อทำเครื่องหมายค่าคงที่ดังนั้นไม่จำเป็นต้องประกาศค่าคงที่เป็นเขตข้อมูลสาธารณะ
biziclop

2
สมมติว่าคู่ทะเยอทะยาน / ตัวตั้งค่ามีความเหมาะสมนั่นคือ มันมักจะไม่
David Thornley

2

นี่เป็นเรื่องส่วนตัว แต่ความเห็นของฉันคือความคิดของภาครัฐ / เอกชนทั้งหมดล้าสมัยและล้าหลัง

ในไพ ธ อนไม่มีสาธารณะ / ส่วนตัว ทุกอย่างเป็นสาธารณะโดยทั่วไป ไม่ได้ทำให้เกิดปัญหามากมาย

ใน Java คุณมักจะสร้างตัวรับสัญญาณ / ตัวตั้งค่าสำหรับแต่ละฟิลด์เพื่อหลีกเลี่ยงความผิดพลาดในการทำเครื่องหมาย "สาธารณะ" (IMHO หากคุณพบว่าตัวเองกำลังทำอยู่คุณควรทำเครื่องหมายว่าเป็นสาธารณะ)


Python อนุญาตให้คุณทำเครื่องหมายสิ่งต่าง ๆ ว่าเป็นส่วนตัวโดยนำหน้าชื่อด้วย __ ไม่ใช่ส่วนตัว 100% เนื่องจากยังคงมีวิธีเข้าถึงตัวแปรและวิธีการเหล่านั้น แต่ใน C # คุณสามารถทำสิ่งที่คล้ายกันกับการสะท้อน
อดัมเลียร์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.