2009-12-21 64 views
68

Tôi có một lớp bao gồm chỉ của các biến thành viên tĩnh và phương pháp tĩnh. Về cơ bản, nó đang phục vụ như một lớp tiện ích đa năng.Thực tiễn không tốt cho một lớp học chỉ có các trường và phương thức tĩnh?

Thực tiễn không tốt cho một lớp chỉ chứa các biến thành viên tĩnh và phương pháp tĩnh?

+28

'java.lang .Math' là phương thức tĩnh 100% với hàm tạo 'private' (không thể được khởi tạo). – Asaph

+0

Không chắc liệu câu hỏi này đã được hỏi trong diễn đàn này chưa. Nhưng nó là một thực hành xấu cho một lớp học để chỉ có các trường tĩnh? Tôi đã thấy rất nhiều lớp học như vậy và theo ý kiến ​​của tôi, họ không phù hợp với OOP. – ka3ak

+0

@ ka3ak Các lớp chỉ có các trường tĩnh được giải quyết một phần trong một vài câu trả lời cho câu hỏi này. –

Trả lời

85

Không, tôi không nghĩ vậy chút nào. Thực hành tồi tệ hơn là có một lớp đầy đủ các phương thức ví dụ không thực sự phụ thuộc vào một cá thể cụ thể. Làm cho chúng tĩnh sẽ cho người dùng biết chính xác họ định sử dụng như thế nào. Ngoài ra, bạn tránh các cảnh báo không cần thiết theo cách này.

EDIT: Như một suy nghĩ, nói chung tôi nghĩ rằng nó tốt đẹp để tránh sử dụng các tính năng ngôn ngữ "chỉ vì", hoặc bởi vì bạn nghĩ rằng đó là "Java cách để làm điều đó". Tôi nhớ lại công việc đầu tiên của mình khi tôi có một lớp đầy đủ các phương thức tiện ích tĩnh và một trong những lập trình viên cao cấp đã nói với tôi rằng tôi đã không khai thác triệt để sức mạnh của OO của Java bằng cách làm cho tất cả các phương thức của tôi "toàn cầu". Cô ấy không có mặt trong nhóm 6 tháng sau đó.

+97

nhắc tôi đừng cản trở bạn. – akf

+7

Ha - không hoàn toàn là những gì tôi ngụ ý để ngụ ý – danben

3

Hoàn toàn hợp lý. Trong thực tế, trong C# bạn có thể định nghĩa một lớp với từ khóa tĩnh đặc biệt cho mục đích này.

13

Âm thanh hợp lý.

Lưu ý: Các lớp thực hiện điều này thường có một hàm tạo riêng không có arg để trình biên dịch đưa ra lỗi nếu một lập trình cố gắng tạo một thể hiện của lớp tĩnh.

+4

Một hàm tạo mặc định riêng tư cũng ngăn cản việc phân loại lớp tĩnh của bạn. – David

+1

là có lý do nào bạn muốn lớp phụ lớp tĩnh? (không thể nghĩ ra một ... Tôi không phải là một chuyên gia ngôn ngữ) –

+4

Ngăn chặn phân lớp phụ trong trường hợp này là "chuyên nghiệp". Có thể ai đó đang làm việc trong dự án của bạn có thể vô tình thử và phân lớp lớp tĩnh của bạn (thông qua lỗi đánh máy hoặc hiểu lầm). Bằng cách thêm một hàm tạo riêng mặc định, bạn sẽ bổ sung thêm ý nghĩa cho lớp của bạn bằng cách thực thi nghiêm ngặt hơn cách nó có thể được sử dụng. – David

2

Cũng lưu ý rằng Java đặc biệt giới thiệu việc nhập khẩu tĩnh: (http://en.wikipedia.org/wiki/Static_import)

nhập tĩnh là một tính năng được giới thiệu trong ngôn ngữ lập trình Java mà thành viên (trường và phương pháp) được xác định trong một lớp học như cộng đồng tĩnh được sử dụng trong mã Java mà không chỉ định lớp trong đó trường được xác định. Tính năng này được đưa vào ngôn ngữ trong phiên bản 5.0.

Tính năng cung cấp một cơ chế typesafe để bao gồm các hằng số vào mã mà không cần phải tham khảo các lớp mà ban đầu được xác định lĩnh vực . Nó cũng giúp loại bỏ thực tiễn tạo giao diện không đổi: một giao diện chỉ có xác định các hằng số sau đó viết một lớp triển khai giao diện đó, là coi việc sử dụng không phù hợp là giao diện [1].

Cơ chế có thể được sử dụng để tham khảo thành viên cá nhân của một lớp:

import static java.lang.Math.PI; 
import static java.lang.Math.pow; 

hoặc tất cả các thành viên tĩnh của một lớp:

import static java.lang.Math.*; 
+0

Tôi nghĩ rằng đây là một chút chủ đề cho những gì anh ta đang hỏi. Nhập tĩnh không liên quan gì đến việc một lớp CHỈ có các thành viên tĩnh hay không; nó hoạt động nếu có. – danben

+1

Cả hai thông tin tốt và một lý lẽ tuyệt vời cho lý do tại sao đây là một cái gì đó chúng tôi có nghĩa là để làm. – Chuck

+0

Xin lỗi, tôi không đồng ý - Tôi nghĩ rằng đó là một lý lẽ cho việc có các phương pháp tĩnh, nhưng nó không nói gì về việc có các lớp không có nghĩa là được khởi tạo. – danben

3

Chỉ cần don' t được mang đi với nó. Lưu ý rằng lớp java.lang.Math chỉ là về các hàm toán học.Bạn cũng có thể có một lớp StringUtilities chứa các hàm xử lý chuỗi phổ biến không có trong API chuẩn, ví dụ. Nhưng nếu lớp của bạn được đặt tên là Tiện ích, ví dụ, đó là một gợi ý mà bạn có thể muốn chia nó ra.

1

Lớp Collections trong Java SDK chỉ có thành viên tĩnh.

Vì vậy, có bạn đi, miễn là bạn có thích biện minh - không phải là một thiết kế xấu của nó

1

phương pháp Utility thường được đặt trong các lớp học với chỉ phương pháp tĩnh (. Như StringUtils) hằng toàn cầu cũng được đặt trong lớp riêng của họ để họ có thể được nhập bằng phần còn lại của mã (thuộc tính public final static.)

Cả hai sử dụng đều khá phổ biến và có các nhà xây dựng mặc định riêng để ngăn không cho chúng được khởi tạo. Khai báo lớp cuối cùng ngăn chặn sai lầm của việc cố gắng ghi đè các phương thức tĩnh.

Nếu bằng static member variables bạn không có nghĩa là hằng số toàn cầu, bạn có thể muốn đặt các phương thức truy cập các biến đó trong một lớp của riêng chúng. Trong trường hợp đó, bạn có thể tập hợp vào những gì các biến đó thực hiện trong mã của bạn không?

1

Theo cách giải thích cứng nhắc về Thiết kế hướng đối tượng, một lớp tiện ích là điều cần tránh.

Vấn đề là nếu bạn làm theo một diễn giải cứng nhắc thì bạn sẽ cần phải buộc lớp của bạn thành một số đối tượng sắp xếp để hoàn thành nhiều thứ.

Ngay cả các nhà thiết kế Java làm cho lớp tiện ích (java.lang.Math nói đến cái tâm)

lựa chọn của bạn là:

double distance = Math.sqrt(x*x + y*y); //using static utility class 

vs:

RootCalculator mySquareRooter = new SquareRootCalculator(); 
mySquareRooter.setValueToRoot(x*x + y*y); 
double distance; 
try{ 
    distance = mySquareRooter.getRoot(); 
} 
catch InvalidParameterException ......yadda yadda yadda.  

Thậm chí nếu chúng ta tránh phương pháp tiết, chúng tôi vẫn có thể kết thúc với:

Mathemetician myMathD00d = new Mathemetician() 
double distance = myMathD00d.sqrt(...); 

trong trường hợp này, .sqrt() vẫn còn tĩnh, vậy thì điểm nào sẽ là tạo đối tượng ở vị trí đầu tiên?

Câu trả lời là, tạo các lớp tiện ích khi tùy chọn khác của bạn sẽ tạo ra một loại lớp nhân viên "công nhân" không có hoặc ít sử dụng cho các biến mẫu.

2

Trong khi tôi đồng ý với ý kiến ​​rằng nó giống như một giải pháp hợp lý (như những người khác đã nêu), một điều bạn có thể muốn xem xét, từ quan điểm thiết kế, tại sao bạn có một lớp chỉ dành cho "tiện ích" mục đích. Các hàm đó có thực sự chung trên toàn bộ hệ thống hay chúng thực sự liên quan đến một số lớp đối tượng cụ thể trong kiến ​​trúc của bạn.

Miễn là bạn đã nghĩ về điều đó, tôi thấy không có vấn đề với giải pháp của bạn.

17

Miễn là lớp không có trạng thái bên trong và về cơ bản cái được gọi là lớp lá (lớp tiện ích rơi vào thể loại này), nói cách khác nó độc lập với các lớp khác. Nó ổn.

Lớp Math là một ví dụ điển hình.

+0

Bạn có một liên kết/bài viết hay liên quan đến các lớp lá/tiện ích không? –

9

Phương pháp tĩnh không làm tôi lo lắng nhiều (ngoại trừ thử nghiệm).

Nói chung, các thành viên tĩnh là mối quan tâm. Ví dụ: nếu ứng dụng của bạn được nhóm lại thì sao? Điều gì về thời gian khởi động - loại khởi tạo đang diễn ra? Để xem xét các vấn đề này và hơn thế nữa, hãy xem this article bởi Gilad Bracha.

+2

+1 để phân biệt giữa các hàm tĩnh (tốt) và trạng thái tĩnh (không rõ ràng) – mikera

0

Tôi sẽ không quan tâm đến lớp tiện ích chứa phương pháp tĩnh.

Tuy nhiên, các thành viên tĩnh về cơ bản là dữ liệu toàn cầu và nên tránh. Chúng có thể được chấp nhận nếu chúng được sử dụng để lưu trữ kết quả của các phương thức tĩnh và như vậy, nhưng nếu chúng được sử dụng như dữ liệu "thực" có thể dẫn đến tất cả các loại vấn đề, chẳng hạn như phụ thuộc ẩn và khó khăn để thiết lập thử nghiệm.

1

Liên kết này http://java.dzone.com/articles/why-static-bad-and-how-avoid dường như đi ngược lại hầu hết các câu trả lời ở đây. Thậm chí nếu nó không chứa biến thành viên (tức là không có trạng thái), một lớp tĩnh vẫn có thể là một ý tưởng tồi vì nó không thể được mô phỏng hoặc mở rộng (được phân lớp), vì vậy nó đang đánh bại một số nguyên tắc của OO

Các vấn đề liên quan