문제

다양한 서브 클래스와 해당 서브 클래스의 인스턴스에서 작동하는 알고리즘이 있고, 알고리즘의 동작이 인스턴스의 특정 서브 클래스가 무엇인지에 따라 약간 변하면 가장 일반적인 객체 지향적 인 방법은 사용하는 것입니다. 가상 방법.

예를 들어 서브 클래스가 DOM 노드이고 알고리즘이 하위 노드를 삽입하는 경우, 해당 알고리즘이 부모 노드가 DOM 요소 (어린이를 가질 수있는)인지 또는 DOM 텍스트 (할 수없는)에 따라 다릅니다. 그래서 insertChildren 방법은 DomNode 기본 클래스, 각각에서 다르게 구현 DomElement 그리고 DomText 서브 클래스.

또 다른 가능성은 인스턴스에게 공통 속성을 제공하는 것입니다. 값은 값을 읽을 수 있습니다. 예를 들어 알고리즘이 읽을 수 있습니다. nodeType 의 속성 DomNode 기본 클래스; 또는 다른 예를 들어, 공통 패킷 헤더를 공유하는 네트워크 패킷의 다른 유형 (서브 클래스)을 가질 수 있으며 패킷 헤더를 읽고 패킷 유형을 확인할 수 있습니다.

나는 다음을 포함하여 런타임 유형 정보를 많이 사용하지 않았습니다.

  • 그만큼 is 그리고 as C#의 키워드
  • 다운 캐스팅
  • Dot Net의 Object.getType 메소드
  • 그만큼 typeid C ++의 연산자

서브 클래스 유형에 따라 새로운 알고리즘을 추가 할 때 클래스 계층에 새로운 가상 메소드를 추가하는 경향이 있습니다.

내 질문은 가상 함수 대신 런타임 유형 정보를 사용하는 것이 언제 적절합니까?

도움이 되었습니까?

해결책

다른 방법이 없을 때. 가상 방법은 항상 선호되지만 때로는 사용할 수 없습니다. 이것이 일어날 수있는 몇 가지 이유가 있지만 가장 일반적인 것은 당신이 함께 일하고 싶은 클래스의 소스 코드가 없거나 변경할 수 없기 때문입니다. 이것은 레거시 시스템이나 폐쇄 소스 상업 라이브러리에서 작업 할 때 종종 발생합니다.

.NET에서는 플러그인과 같이 새로운 어셈블리를 즉석에로드해야하며 일반적으로 기본 클래스가 없지만 오리 타이핑과 같은 것을 사용해야합니다.

다른 팁

C ++에서는 다른 모호한 사례 (주로 열등한 디자인 선택을 다루는) 중에서 RTTI는 소위를 구현하는 방법입니다. 다중 방법.

이 이벤트 핸들러는 일반적으로 공통 조상에게 객체를 다운 캐스트하기 때문에이 구성 ( "is"및 "as")은 델파이 개발자에게 매우 친숙합니다. 예를 들어, 이벤트 onclick은 객체의 유형에 관계없이 tbutton, tlistbox 또는 기타이든 상관없이 유일한 Argurment 발신자를 통과합니다. 이 객체에 대해 더 알고 싶다면 "AS"를 통해 액세스해야하지만 예외를 피하기 위해서는 "IS"와 함께 확인할 수 있습니다. 이 다운 캐스팅을 통해 엄격한 클래스 유형 검사에서는 불가능한 객체 및 메소드의 설계 유형 바인딩이 가능합니다. 사용자가 버튼이나 ListBox를 클릭하면 동일한 작업을 원하지만 다른 기능의 프로토 타입을 제공하면 동일한 프로 시저에 바인딩 할 수 없습니다.

보다 일반적인 경우, 객체는 예를 들어 객체가 변경되었음을 알리는 함수를 호출 할 수 있습니다. 그러나 사전에 그것은 목적지가 그를 "개인적으로"(그와 함께) 알 수있는 가능성을 남기지 만 반드시 그런 것은 아닙니다. 그것은 모든 대상의 가장 일반적인 조상으로 자아를 전달함으로써 이것을합니다 (델파이 케이스의 Tobject).

Dynamic_cast <>는 내가 올바르게 기억한다면 RTTI에 따라 다릅니다. 객체가 공간 포인터를 통과 할 때 (어떤 이유로 든 저것 일어날 수 있습니다).

즉, 나는 10 년간의 프로 C ++ 유지 보수 작업에서 야생에서 typeof ()를 보지 못했습니다. (운 좋게.)

런 타임 유형 확인이 정상인 경우보다 효과적인 C#을 참조 할 수 있습니다.

항목 3. 런타임 유형 확인을 사용하여 일반 알고리즘을 전문화합니다

단순히 새로운 유형 매개 변수를 지정하여 제네릭을 쉽게 재사용 할 수 있습니다. 새로운 유형 매개 변수가있는 새로운 인스턴스화는 유사한 기능을 갖는 새로운 유형을 의미합니다.

코드를 적게 쓰기 때문에이 모든 것이 좋습니다. 그러나 때로는 더 일반적인 것은 더 구체적이지만 명확하게 우수한 알고리즘을 이용하지 않는다는 것을 의미합니다. C# 언어 규칙은 이것을 고려합니다. 유형 매개 변수에 더 큰 기능이있을 때 알고리즘이 더 효율적일 수 있음을 인식하고 해당 특정 코드를 작성하는 것입니다. 또한, 다른 제약 조건을 지정하는 두 번째 일반 유형을 만드는 것이 항상 작동하지는 않습니다. 일반적인 인스턴스화는 런타임 유형이 아닌 객체의 컴파일 타임 유형을 기반으로합니다. 이를 고려하지 않으면 가능한 효율성을 놓칠 수 있습니다.

예를 들어, ienumerable을 통해 표시되는 일련의 항목에 리버스 주문 열거를 제공하는 클래스를 작성한다고 가정 해 봅시다u003CT> . 거꾸로 열거하려면 반복하고 색인가 액세스와 같은 목록이있는 중간 컬렉션에 항목을 복사 할 수 있습니다.u003CT> 그리고 인덱서 액세스를 거꾸로 사용하여 해당 컬렉션을 열거하는 것보다. 그러나 원래의 ienumerable이 Ilist를 이용하지 말고 항목을 거꾸로 반복하기 위해보다 성능있는 방법 (중간 수집에 복사하지 않고)을 제공하지 않는 이유는 무엇입니까? 따라서 기본적으로 그것은 우리가 이용할 수 있지만 여전히 동일한 동작을 제공 할 수 있지만 (반복 순서를 거꾸로) 제공 할 수 있습니다.

그러나 일반적으로 런타임 유형 검사를 신중하게 고려하고 Liskov 대체 원칙을 위반하지 않도록해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top