2013-02-12 38 views
5

Tôi có một danh sách các đối tượng mở rộng từ một lớp cơ sở. Bây giờ tôi muốn áp dụng một hoạt động cụ thể chỉ trên một thể hiện của các lớp trong danh sách.Ví dụ là một thực hành tốt?

Việc sử dụng instanceof có thực hành tốt ở đó không? Hoặc tôi có nên thay đổi các đối tượng khác nhau không, ví dụ: tùy chỉnh enum?

abstract class Base; 
class Foo extends Base; 
class Bar extends Base; 

List<Base> bases; 

for (Base base : bases) { 
    if (base instanceof Bar.class) { 
    //execute my custom operation on the base object 
    doSomething((Bar) base); 
    } 
} 

Nếu cách tiếp cận đó không tốt đẹp nói chung, làm cách nào tôi có thể làm tốt hơn?

+6

Sử dụng đa hình; đó là lý do tại sao nó tồn tại. –

+0

chính xác - thay vì doSomething (base) - bạn nên thực hiện một số base.doSomething(), được ghi đè trong foo.doSomething(). Google đa hình java - hoặc - ghi đè lên phương thức java. –

+3

Tôi thích câu trả lời cụ thể này: http://www.javapractices.com/topic/TopicAction.do?Id=31. Tôi nhận ra C++ và Java là khác nhau nhưng ** "Bất cứ lúc nào bạn thấy mình viết mã của biểu mẫu" nếu đối tượng thuộc loại T1, sau đó làm điều gì đó, nhưng nếu nó thuộc loại T2, thì hãy làm gì đó khác, "tát bản thân. * * – thang

Trả lời

3

Thực sự không có lý do gì để sử dụng trường hợp ở đây. Nó có thể có ý nghĩa để có các lớp cơ sở mặc định hành vi để không làm gì và ghi đè nó trong mở rộng các lớp học khi cần thiết. Bằng cách này bạn chỉ ghi đè lên nó nếu cần thiết (tôi on.y để lại điều này như là một lớp trừu tượng để làm theo với câu hỏi của nó không cần thiết cho ví dụ này). Ví dụ:

abstract class Base{ 
    public void doSomething(){} 
} 

public class B0 extends Base{ 
    @Override 
    public void doSomething(){//actually do something} 
} 

public class B1 extends Base{} 

Một ví dụ của việc sử dụng này có thể là một cái gì đó như:

public class SomeOtherClass{ 
    public void something(List<Base> bases){ 
     for(Base base:bases) 
      base.doSomething(); 
    } 
} 
+0

Đó là một ý tưởng rất hay vì tôi có thể bỏ qua việc triển khai thực hiện trên các lớp mà không nên làm gì trên lời gọi phương thức đó. – membersound

2
abstract class Base;//abstract function doSomething() 
class Foo extends Base;//implements doSomething() 
class Bar extends Base;//dito 

List<Base> bases; 

for (Base base : bases) { 
    base.doSomething(); 
} 

Để trả lời câu hỏi của bạn: bạn không nên sử dụng instanceof.

+3

Tại sao bây giờ bạn đang kiểm tra instanceof .. Bạn không phải – smk

+2

Cú pháp sai, nó phải là "' cơ sở instanceof Bar' " – shuangwhywhy

+0

Tại sao u sử dụng instanceof khi nó được cho là không phải là một ý tưởng tốt? – membersound

1

Instance của không phải là một thực hành tốt ở đây.

Giải pháp đúng sẽ phụ thuộc vào chính xác những gì đang xảy ra bên trong phương thức doSomething đó. Nếu bạn làm theo cách của bạn, ngoài những thứ khác, bạn vi phạm Liskov Substitution Principle. Tôi giả sử rằng bạn đã quyết định rằng bạn cần các hệ thống phân cấp này ở vị trí đầu tiên vì một cái gì đó và tôi cũng giả định rằng các kiểu con có một số hành vi nhiều hơn chỉ có phương thức doSomething. Trong trường hợp này, những gì bạn có thể làm được hiển thị bên dưới. Về cơ bản chỉ có các loại mà nên doSomething thực sự làm điều đó và phần còn lại của các loại làm một cái gì đó như no operation. Bằng cách đó bạn có thể sử dụng các đối tượng này mà không cần phải biết chúng thực sự là loại gì.

Bạn cũng nên tự hỏi mình có thực sự cần lớp cơ sở là lớp trừu tượng hay không. Có lẽ tất cả những gì bạn cần là một giao diện. Có thể có cách tiếp cận tốt hơn nhưng dựa trên thông tin tôi có và những gì tôi đã giả định thì điều này có vẻ không sao.

public abstract class Base 
{ 
    public abstract void doSomething(); 

    public void someOtherMethod() 
    { 
     // which does stuff 
    } 
} 

public class SubTypeWhichCanDoSomething extends Base 
{ 
    @Override 
    public void doSomething() 
    { 
     // actually implement method and DO something 
    } 
} 

public class DoesNothing extends Base 
{ 
    @Override 
    public void doSomething() 
    { 
     // does nothing 
     return; 
    } 
} 

// then your code looks like these 
for(Base base : bases) 
{ 
    base.doSomething(); 
} 
Các vấn đề liên quan