2011-07-06 4 views
10

object oriented programming의 본질에 대해 instanceof 키워드를 사용하고 있습니까? 나쁜 프로그래밍 방식인가요? instanceof 키워드를 사용하면 디자인이 좋지 않을 수 있다는 것을 알게되었습니다. 더 나은 해결 방법은 무엇입니까?instanceof 키워드 사용

+0

사용중인 인스턴스는 무엇입니까? 문제가 목록에없는 경우 해결 방법을 제공하기가 어렵습니다. – Kal

+0

@aps 당신이 걱정하는'instanceof'의 사용법을 보여줄 수 있습니까? –

+0

나는 그것을 사용하지 않을거야. 하지만 누군가가 instanceof를 사용한다면 프로그래밍이 좋지 않다고 생각하는 이유는 무엇입니까? – aps

답변

14

일반적으로 말해서. 특정 클래스에 속하는 모든 코드를 유지하는 것이 가장 좋으며, 일반적으로 instanceof을 사용하면 해당 클래스 외부에 일부 코드를 넣었다는 의미입니다. 이 간단한 예제를

봐는 :

public class Animal 
{ 
} 

public class Dog extends Animal 
{ 
} 

public class Cat extends Animal 
{ 
} 

public class SomeOtherClass 
{ 
    public abstract String speak(Animal a) 
    { 
    String word = ""; 

    if (a instanceof Dog) 
    { 
     word = "woof"; 
    } 
    else if (a instanceof Cat) 
    { 
     word = "miaow"; 
    } 

    return word; 
    } 
} 

이상적으로, 우리는 우리의 프로그램의 주위에 개는 개 클래스에 포함되는 특정의 행동의 모든보다는 확산을 싶습니다. 우리는 다음과 같이 우리의 프로그램을 다시 작성하여이를 변경할 수 있습니다 : 우리는 Animalspeak 방법을 가지고 있어야한다는 지정한

public abstract class Animal 
{ 
    public String speak(); 
} 

public class Dog extends Animal 
{ 
    public String speak() 
    { 
    return "woof"; 
    } 
} 

public class Cat extends Animal 
{ 
    public String speak() 
    { 
    return "miaow"; 
    } 
} 

public class SomeOtherClass 
{ 
    public String speak(Animal a) 
    { 
    return a.speak(); 
    } 
} 

. 이제 SomeOtherClass은 동물의 각 유형에 대한 세부 정보를 알 필요가 없습니다. Animal의 하위 클래스로 전달할 수 있습니다.

+2

그냥 여분으로 point :이 대답에서 말했듯이'instanceof' 문제는 당신이 subtype을 지정할 필요가있다. 하위 유형이 변경되면 어떻게됩니까? 그런 다음'instanceof' 테스트를 다시 작성해야합니다. 그러나 동적 바인딩 및 다형성을 사용하면 차이가 발생하지 않고 계속 작동합니다. – adamjmarkham

+0

+1 : "어떻게해야할까요?"D –

+0

Animal에서 '말하기'를 '추상적'으로해야합니까, 아니면 모든 동물이 음소거를 시작해야합니까? –

2

명이 같은 일을하는 데 사용할 수 있기 때문에 낙담 것 :

if(myAnimal instanceof Dog) 
    ((Dog)myAnimal).bark(); 
else(myAnimal instanceof Cat) 
    ((Cat)myAnimal).meow(); 

대신 Animalspeak() 방법 DogCat 상속이 있어야합니다. 다형성과 동적 바인딩과 적절한 OOP, 당신은 단순히 당신이 개체의 특정 유형을 결정하기 위해 instanceof를 사용해야하는 일부 인스턴스가, 그러나

myAnimal.speak(); 

할 것입니다. 아마도 귀하의 집에 Animals의 목록이 있고 walk()에 대해 취하고 싶은 유일한 것들은 Dog입니다. 이 경우 귀하는 귀하의 목록을 반복하고 개만 walk() 개를 찾으십시오.

+2

나는 우리가 동시에 이것들을 쓰고 있었고 둘 다 동물의 예를 찾아 갔다는 사실을 매우 좋아한다. :) –

+2

나는 내 의견에 똑같이 당신의 게시물에 똑같은 것을 덧붙일 예정이다. – tskuzzy

3

다운 캐스팅에 대한 다형성 및 동적 바인딩을 선호하고 instanceof. 이것은 "OO Way"이며 하위 유형에 대해 알 필요가없는 코드를 작성할 수 있습니다.

abstract class Animal { 
    public abstract void talk(); 
    //... 
} 

class Dog extends Animal { 
    public void talk() { 
     System.out.println("Woof!"); 
    } 
    //... 
} 

class Cat extends Animal { 
    public void talk() { 
     System.out.println("Meow!"); 
    } 
    //... 
} 

class Hippopotamus extends Animal { 
    public void talk() { 
     System.out.println("Roar!"); 
    } 
    //... 
} 

class Main { 

    public static void main(String[] args) { 

     makeItTalk(new Cat()); 
     makeItTalk(new Dog()); 
     makeItTalk(new Hippopotamus()); 
    } 

    public static void makeItTalk(Animal animal) { 

     animal.talk(); 
    } 
} 
+2

나는 '벨로우 (bellow)'가 하마에게 더 적절한 음소 일 것이라고 생각한다. :). 서브 클래 싱하여 기본 동작을 재정의 할 것입니다. +1 당신의 디자인도 나를 수있게 해줍니다. – Perception

3

동일한 효과 thomson_matt의 예에서와 같은 가상의 방법을 통해 달성 될 수있을 때 instanceof의 사용이 권장되지. 그러나 경우에 따라 instanceof을 사용해야합니다. 예를 들어 코드가 외부 소스 (예 : Object을 반환하는 네트워크 또는 타사 API)에서 Object를 가져올 때이 객체의 유형이 무엇인지 결정하고 적절하게 동작해야합니다.

4

가상 메소드를 홍보하는 데 유용한 답변이 많이 있지만 instanceof에도 그 용도가 있습니다. List<Event>을 반복하여 모든 Urgent 개체를 가져 오는 것으로 가정 해 보겠습니다. isUrgent()을 사용하여이 작업을 수행 할 수도 있지만 필연적으로 더 간결하고 읽기 쉬운 것인지 확실하지 않습니다.또한 isUrgent()Event이 해당 하위 클래스가 해당 속성을 소유 할 수 있음을 알리도록 요구합니다.

  • 은 모듈성 원칙에 대해 무언가로 간주 될 수 있습니다. Event이 (가) 수정할 수없는 라이브러리에 속한 경우
  • 조차도 불가능합니다.
  • 3

    핵심은 instanceof가 일반적인 "정상적인 습관"의 일부로 보지 않는 것입니다. 일반적으로 인트로 스펙 션과 마찬가지로 instanceof는 특히 비정형적인 상황에서 사용하기위한 특수 도구입니다. 'instanceof'를 사용할 때마다 더 일반적으로 반사와 같은 플랫폼의 다른 '특수'부분을 사용하는 경우가 있습니다.

    당신이 그것을 사용하고있을 때마다, 당신이하고있는 일이 더 우아하고 실용적인 대안이 없다는 것에 동의한다는 한, 괜찮습니다. 말했다

    , 일상 프로그램에서 가장 일반적인 상황은 아마 :

    • 구현 등호()
    • 읽기 직렬화 된 객체
    • 당신의 배열/모음을 제공하고 약간 다른 경우를 항목 프레임/컨테이너 내의 JComponents를 열거 해, 형태에 응해 액션을 취합니다.

    당신이 시도 할 수있는 엄지 손가락 규칙은 라이브러리 사용자가 'instanceof'를 사용해야 만하는 것이 아니라 라이브러리 내부에 'instanceof'가있는 경우를 요구하는 것입니다.

    다른 식으로 말하면 질문의 프레임을 다시 만들어야합니다. "intsanceof는의 경우 의 해결 방법이 무엇입니까?"

    +0

    thomson_matt는 instanceof의 잘못된 사용에 대한 좋은 예를 제공합니다. 이제 나는 그가 말한 모든 조건들이 사실 인 상황을 가지고있다. Say Animal은 추상 클래스이고, Cat과 Dog은 그 서브 클래스입니다. 그래서 자연스럽게 각 동물이 만들어야하는 소리는 그 자체의 클래스 자체에 캡슐화되어야합니다. 하지만 다른 종류의 다른 동물에 반응하는 다른 클래스의 Mouse가 있다고 가정 해 봅시다. 개가 있다면 Dog 's 경로를 피하는 것 외에는 아무것도하지 않습니다. 고양이 인 경우 숨기기를 시도합니다. 그런 상황에서 instanceof는 괜찮습니까? 아니면 더 좋은 방법이 있습니까? – aps

    +2

    Mouse 객체에 대해 여러 개의 reactTo (...) 메소드를 가질 수 있으며 각 동물 유형에 하나씩 사용할 수 있으며 마우스로 반응시키려는 동물을 전달할 수 있습니다. –

    0

    생성 팩토리 (아래 참조)의 경우는 어떻습니까? 이 경우, 동물 서브 클래스가 새장을 작성하는 방법을 알고있는 것이 적절하지 않다고 생각합니다. 그것은 Animal이 무엇인지에 대한 범위를 벗어난 것처럼 보이며 Animal 서브 클래스가 Animal이 내재적이지 않은 행동을 취하게합니다.

    public static Cage createCage(Animal animal) { 
        if (animal instanceof Dog) 
        return new DogHouse(); 
        else if (animal instanceof Lion) 
        return new SteelCage(); 
        else if (animal instanceof Chicken) 
        return new ChickenWiredCage(); 
        else if (animal instanceof AlienPreditor) 
        return new ForceFieldCage(); 
        ... 
        else 
        return new GenericCage(); 
    } 
    
    0

    instaceOf 조작의 또 다른 사용법은 오류 처리 일 수 있습니다. 당신은 예외 유사한 오류 처리를 가지고 있고, 당신이 그것을 한 곳에서 모두를 원한다면 당신은 사용할 수 있습니다

    위의 코드와
    public void handleError(Throwable t, HttpServletRequest req) { 
        if (t instaceOf ValidationException) { 
           ...doSomewthing...... 
        } else if (t instaceOf DataException) { 
           ...doSomewthing...... 
        } else if (t instaceOf DataException) { 
           ...doSomewthing...... 
        } else { 
           ...doSomewthing...... 
        } 
    
    } 
    

    , 당신은 피할 수 많은

    } catch <Exception> { 
    

    블록이 대신하도록 한

    } catch (Throwable t) { 
        handleError(t, request); 
        return "errorPage" or whateveryouwant; 
    } 
    

    또한, 한 가지 더입니다 .. 당신은 자바 소스 코드, 당신은 instaceof의 많은 용도를 찾을 수 확인

    ,369입니다

    좋은 링크 하나 : article about usage of instaceof