Có phải các lĩnh vực công cộng của Java chỉ là một lỗ hổng thiết kế lịch sử bi thảm vào thời điểm này? [đóng cửa]


17

Có vẻ như chính thống Java ở điểm này về cơ bản người ta không bao giờ nên sử dụng các trường công khai cho trạng thái đối tượng. . Hoặc có một lập luận hợp lý rằng chúng là một phần hữu ích và quan trọng của ngôn ngữ, ngay cả ngày nay?

Cảm ơn!

Cập nhật: Tôi biết về các cách tiếp cận thanh lịch hơn, chẳng hạn như trong C #, Python, Groovy, v.v. Tôi không trực tiếp tìm kiếm các ví dụ đó. Tôi thực sự chỉ tự hỏi liệu vẫn còn ai đó ở sâu trong hầm, lẩm bẩm về việc các lĩnh vực công cộng thực sự tuyệt vời như thế nào, và quần chúng chỉ là những con cừu, v.v.

Cập nhật 2: Các trường công khai cuối cùng tĩnh rõ ràng là cách tiêu chuẩn để tạo các hằng công khai. Tôi đã đề cập nhiều hơn đến việc sử dụng các trường công khai cho trạng thái đối tượng (thậm chí trạng thái bất biến). Tôi nghĩ rằng nó có vẻ như là một lỗ hổng thiết kế rằng người ta nên sử dụng các trường công khai cho các hằng số, nhưng không phải cho nhà nước, một quy tắc ngôn ngữ nên được thực thi một cách tự nhiên, theo cú pháp, chứ không phải theo hướng dẫn.


2
Cơ sở của bạn là gì mà họ thực sự là một lỗ hổng?
Aaron McIver

1
Bây giờ có một cách khác để tạo các biểu thức hằng biểu tượng trong Java không?
Edward Strange

@Aaron Tôi không nói rằng họ là một lỗ hổng, tôi đã nói rằng tôi đã nhận thấy nó là chính thống vào thời điểm này rằng người ta không bao giờ nên sử dụng các lĩnh vực công cộng. Nhận thức đó có thể sai, nhưng đó thực sự là những gì tôi đã nhận thấy.
Avi Flax

@Crazy Eddie Tôi quên mất việc sử dụng đó, tôi đã suy nghĩ nhiều hơn về việc sử dụng phổ biến hơn các lĩnh vực, nhà nước. Tôi sẽ chỉnh sửa câu hỏi.
Avi Flax

Câu trả lời:


14

Tôi thích chúng, miễn là trường cuối cùng và chỉ được sử dụng nội bộ trong ứng dụng, không được hiển thị trong API cho các ứng dụng khác. Điều này giữ cho mã của bạn ngắn hơn và dễ đọc hơn.

Bạn không nên phơi bày các trường công khai trong API bởi vì bằng cách hiển thị các trường công khai, bạn cũng phơi bày việc triển khai. Nếu bạn trưng bày nó như một getXXX()phương thức thay thế, bạn có thể thay đổi việc triển khai mà không thay đổi giao diện API. Ví dụ: bạn có thể thay đổi và nhận giá trị từ một dịch vụ từ xa, nhưng các ứng dụng sử dụng API không cần biết điều này.

Đây là một thiết kế khả thi cho public finalcác trường trong các lớp bất biến .

Từ Java hiệu quả :

Mục 14: Trong các lớp công khai, sử dụng các phương thức truy cập, không phải các trường công khai

... Nếu một lớp là gói riêng tư hoặc là một lớp lồng riêng, thì không có gì sai khi phơi bày các trường dữ liệu của nó. Cách tiếp cận này tạo ra sự lộn xộn ít hơn so với phương pháp tiếp cận phương pháp truy cập.

Mặc dù không bao giờ là một ý tưởng tốt cho một lớp học công khai trực tiếp các trường, nhưng nó sẽ ít gây hại hơn nếu các trường là bất biến.

Xem thêm Tại sao tôi không nên sử dụng POJO bất biến thay vì JavaBeans?


Chỉ cần tự hỏi, lý do của bạn để không phơi bày nó trong một API là gì?
Steven Jeuris

2
@Steven: Bởi vì bằng cách phơi bày các lĩnh vực công cộng, bạn cũng phơi bày việc thực hiện. Nếu bạn trưng bày nó như một getXXX()phương thức thay thế, bạn có thể thay đổi việc triển khai mà không thay đổi giao diện API. Ví dụ: bạn có thể thay đổi và nhận giá trị từ một dịch vụ từ xa, nhưng các ứng dụng sử dụng API không cần biết điều này.
Jonas

@Jonas: Những người đó thường không phải là ứng cử viên cho hằng số ở vị trí đầu tiên.
Steven Jeuris

@Steven: Tôi không nói về hằng số ở vị trí đầu tiên mà là các trường cuối cùng công khai trong các lớp không thay đổi . Ví dụ, xem Tại sao tôi không nên sử dụng POJO bất biến thay vì JavaBeans?
Jonas

@Jonas: Đó cũng là một trường hợp sử dụng tốt đẹp! Có lẽ nó hữu ích để cập nhật câu trả lời của bạn một chút để làm rõ.
Steven Jeuris

9

Việc sử dụng các cặp phương thức get / set là lỗ hổng thiết kế lịch sử bi thảm. Tôi không thể nghĩ về một ngôn ngữ khác thực hiện các thuộc tính bằng lời nói và không hiệu quả.


1
Mặc dù đúng, điều này có phần tiếp tuyến với điểm của câu hỏi, về cơ bản là đưa ra lựa chọn giữa phương thức set / get và trường công khai, có lý do chính đáng nào để thích trường trong một số trường hợp không? Các ngôn ngữ khác cung cấp giải pháp tốt hơn cho vấn đề dường như không liên quan.
Jules

5

Tôi nghĩ các trường công khai là ổn đối với một lớp về cơ bản là một loại giá trị như số phức hoặc một điểm, trong đó lớp thực hiện ít hơn các kiểu nguyên thủy nhóm với nhau như cấu trúc kiểu C và có thể định nghĩa một vài toán tử.


2
java.awt.Pointvà bạn bè là một cơn ác mộng.
Tom Hawtin - tackline

@ TomHawtin-tackline: Vấn đề Pointlà không rõ liệu một biến loại Pointcó nghĩa là gói gọn một vị trí hay được cho là gói gọn danh tính của một thực thể với vị trí có thể thay đổi. Về mặt khái niệm, tôi sẽ coi mã đi qua Pointgiống như mã đi qua các mảng.
supercat

Vì vậy, nếu tôi nhận được một Pointvà sửa đổi nó, tôi nên mong đợi đối tượng mà nó đề cập đến để cập nhật sạch sẽ trên màn hình? Không, vấn đề với Pointnó là nó có thể thay đổi. Chúng tôi đã có String/ StringBuffernhưng ý tưởng dường như không được thông qua. / Vượt qua các mảng xung quanh không có vấn đề tương tự.
Tom Hawtin - tackline

5

Để xác định hằng số công cộng nó vẫn hữu ích. Ví dụ

chung kết tĩnh tĩnh int DAYS_IN_WEEK = 7;

Tuy nhiên, vẫn thích enum nếu có thể. Ví dụ

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

Để mô phỏng các lớp cấu trúc đơn giản, nó cũng hữu ích. Không có lý do để tạo một getter và setter cho mọi lĩnh vực, khi tất cả chúng đều công khai.

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

Nhưng sau đó, một lần nữa, nhiều người cho rằng các cấu trúc không có chỗ trong một ngôn ngữ như Java ...

1
@delnan: Chúng gần giống như JavaBeans, nhưng JavaBeans dài dòng hơn nhiều và không phải là chủ đề an toàn. Xem tại sao tôi không nên sử dụng POJO bất biến thay vì JavaBeans?
Jonas

Một số quan sát cụ thể của Android: Enums chậm đánh giá hơn ints và nên tránh. Ngoài ra, các trường thường xuyên được truy cập bởi setters và getters trong các vòng lặp chặt chẽ cũng có thể được hưởng lợi từ việc công khai.
Thợ làm móng

2

Trước khi IDE trở nên phổ biến, làm cho tất cả các lĩnh vực của bạn được công khai là một công cụ mạnh mẽ để tạo ra các nguyên mẫu / bằng chứng về các khái niệm một cách nhanh chóng.

Ngày nay có rất ít lý do để sử dụng chúng, khi bạn có thể tạo một cặp getter / setter chỉ với một cú nhấp chuột.


4
Nhưng 10 public finallĩnh vực dễ đọc hơn 10 getXXX()phương thức.
Jonas

1
@Jonas Vâng, nhưng chúng tôi không nói về các lĩnh vực cuối cùng ở đây. Nếu các trường cuối cùng công khai của bạn cũng là tĩnh, chúng là hằng số và một consttừ khóa là đủ, nếu chúng không tĩnh, chúng là vi phạm nghiêm trọng về đóng gói.
biziclop

3
@biziclop theo Wikipedia : "mặc dù được bảo lưu như một từ khóa trong Java, const không được sử dụng và không có chức năng"
Avi Flax

@Avi Flax Vâng, nhưng nó có thể đã được sử dụng để đánh dấu các hằng số, do đó loại bỏ sự cần thiết phải khai báo các hằng số là các trường công khai.
biziclop

2
Giả sử một cặp getter / setter hoàn toàn phù hợp, đó là. Nó thường không.
David Thornley

2

Điều này là chủ quan, nhưng ý kiến ​​của tôi là toàn bộ quan niệm công / tư đã lỗi thời và lạc hậu.

Trong python không có công khai / riêng tư; tất cả mọi thứ là công khai về cơ bản. Không gây ra nhiều vấn đề.

Trong Java, bạn có xu hướng tạo ra các getters / setters vô nghĩa cho từng trường để tránh tội lỗi đánh dấu chúng là "công khai". (IMHO nếu bạn thấy mình làm điều đó, bạn chỉ nên đánh dấu chúng công khai).


Python không cho phép bạn đánh dấu mọi thứ là riêng tư bằng cách thêm tiền tố vào tên bằng __. Nó không riêng tư 100%, vì vẫn có cách để truy cập các biến và phương thức đó, nhưng sau đó trong C #, bạn có thể thực hiện những điều tương tự với sự phản chiếu.
Adam Lear
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.