2015-06-09 14 views
6

Ngôn ngữ lập trình hướng đối tượng, ví dụ: java, C#, ... hỗ trợ đối tượng typecasting. Ví dụ này là hoàn toàn hợp lệ trong java:Đối tượng có thực hành tốt không?

URL url = new URL("url");  
URLConnection conn = url.openConnection(); 

if(!conn instanceof HttpURLConnection) 
    throw new Exception("not http request"); 

HttpURLConnection con = (HttpURLConnection) conn; 

Hoặc một ví dụ khác cơ bản mà tôi đã cố gắng:

public class Base 
{ 
    public void base(){} 
} 

public class Derived extends Base 
{ 
    public void derived(){} 
} 

Base b = new Derived(); 
b.base(); 

nguồn gốc lớp có tất cả các lớp phương pháp cơ sở có, cộng thêm. Không có lý do tại sao bạn không thể tạo lớp cơ sở bằng cách gọi hàm tạo lớp dẫn xuất.

Tôi cũng đã xem liên kết này http://www.volantec.biz/castingObjects.htm giải thích cách thức hoạt động của đối tượng typecasting nội bộ. Cho đến nay, ok.

Nhưng tại sao ví dụ đầu tiên không sử dụng HttpURLConnection con = new HttpURLConnection("url address") (Tôi biết HttpURLConnection là một lớp trừu tượng). Nó chỉ có vẻ rõ ràng hơn, đơn giản hơn. Mặt khác, khi bạn đang giao dịch với interfaces, object typecasting comes in handy. Một ví dụ khác là danh sách List<Object>, đôi khi tôi thấy trong một số lớp. Nó có nghĩa là bạn có thể lưu mọi lớp có thể trong danh sách này. Sau đó bạn chỉ có thể truyền nó đến bản gốc, nếu bạn biết nó là loại gì. Sẽ không rõ ràng hơn khi chỉ lưu các lớp cụ thể vào danh sách tức là List<String>, List<MyClass>. Có sử dụng List<Object> thực hành thiết kế hay không?

+2

Bắt buộc truyền tới 'HttpURLConnection' là ví dụ hoàn hảo về OOD xấu. Về các danh sách chung: nó phụ thuộc, nhưng tôi thà đi cho các danh sách được tham số hóa càng nhiều càng tốt, vì vậy tôi có thể bắt được rất nhiều loại ngoại lệ kiểu thời gian chạy lúc biên dịch. –

+3

Vâng, câu trả lời là trong câu hỏi: HttpUrlConnection là một lớp trừu tượng, vì vậy bạn không thể tạo một thể hiện của HttpUrlConnection. Chỉ có một lớp con. Và đó là những gì url.openConnection() làm. –

+0

@JBNizet Tôi đã đề cập rằng trong ngoặc đơn. Tôi biết rằng HttpURLConnection là một lớp trừu tượng, do đó bạn không thể tạo một cá thể giống như bạn đã đề cập. Bạn nói đúng, tôi chỉ muốn chứng minh điều đó, có thể một số ví dụ khác là phù hợp hơn. – broadband

Trả lời

7

Khi thiết kế một hệ thống phân cấp lớp, bạn luôn phải giữ Liskov's Substitution Principle (aka, LSP) trong tâm trí:

loại nguồn gốc phải hoàn toàn thể thay thế cho các loại cơ sở của họ.

Nói cách khác, để quyết định xem bạn nên mở rộng một lớp, bạn nên tự hỏi liệu các thành phần phụ thuộc vào lớp mới của bạn sẽ được phục vụ tốt nếu bạn thay đổi nó thành lớp cơ sở của nó.

Vấn đề với việc đúc là nếu bạn cần nó để chuyển đổi đối tượng lớp cơ sở thành một đối tượng lớp có nguồn gốc, điều đó có nghĩa là bạn đang vi phạm LSP.

Nếu bạn cần đảm bảo rằng đối tượng là từ một triển khai cụ thể khi bạn đang mong đợi một giao diện, thì chắc chắn có điều gì đó sai với thiết kế của bạn.

Giao diện giống như hợp đồng. Nếu bạn đang sử dụng phương thức triển khai không có trong giao diện, điều đó có nghĩa là bạn đang phá vỡ hợp đồng đó, tạo ra sự liên kết giữa mã của bạn và triển khai.

Hãy nhớ rằng mã của bạn luôn phải là rely on abstractions rather than concretions.

0

bằng cách truyền với lớp Object cơ bản cung cấp mọi quyền có sẵn cho lớp dẫn xuất, đó là chức năng sẽ không bao giờ từ chối tham số sắp tới, vì bạn đã cung cấp cho đối tượng sẽ được truy cập để nguy hiểm, và theo @ Henrique đang nói rằng nó là đúng mà nếu bạn cần phải chắc chắn rằng một đối tượng là một thực hiện cụ thể khi bạn đang mong đợi một giao diện, sau đó chắc chắn là cái gì đó sai với thiết kế của bạn.

+1

xin vui lòng tránh dạng ngắn của tiếng Anh – lalithkumar

+0

Api được thiết kế bởi Java - https://docs.oracle.com/javase/7/docs/api/java/net/HttpURLConnection.html. – broadband

+0

vui lòng đề cập đến tham chiếu đầy đủ vì ý nghĩa của từ 'API được thiết kế bởi JAVA' –

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