상속과 다형성이 왜 그렇게 널리 사용됩니까? 지혜에 의문을 가지기 시작합니다. 나는 학교에서

함수형 프로그래밍과 같은 다른 프로그래밍 패러다임에 대해 더 많이 배울수록 상속 및 다형성과 같은 OOP 개념의 지혜에 의문을 가지기 시작합니다. 나는 학교에서 상속과 다형성에 대해 처음 배웠고, 당시에 다형성은 쉽게 확장 할 수있는 일반적인 코드를 작성하는 훌륭한 방법 인 것처럼 보였다.

그러나 오리 타이핑 (동적 및 정적)과 고차 함수와 같은 기능적 특징에 직면하여, 나는 객체들 사이의 연약한 관계에 기초하여 불필요한 제한을 부과하는 것으로 상속과 다형성을 살펴보기 시작했습니다. 다형성의 기본 개념은 함수를 한 번 작성하고 나중에 원래 함수를 변경하지 않고 프로그램에 새로운 기능을 추가 할 수 있다는 것입니다. 필요한 메소드를 구현하는 다른 파생 클래스를 작성하기 만하면됩니다.

그러나 이것은 파이썬과 같은 동적 언어이든 C ++과 같은 정적 언어이든 오리 타이핑을 통해 달성하기가 훨씬 간단합니다.

예를 들어, 다음 Python 함수와 정적 C ++에 해당하는 것을 고려하십시오.

def foo(obj):
   obj.doSomething()

template <class Obj>
void foo(Obj& obj)
{
   obj.doSomething();
}

OOP에 해당하는 것은 다음 Java 코드와 같습니다.

public void foo(DoSomethingable obj)
{
  obj.doSomething();
}

물론 가장 큰 차이점은 Java 버전이 작동하려면 인터페이스 또는 상속 계층 구조를 작성해야한다는 것입니다. 따라서 Java 버전은 더 많은 작업이 필요하며 유연성이 떨어집니다. 또한 대부분의 실제 상속 계층 구조가 다소 불안정하다는 것을 알았습니다. 우리는 모두 모양과 동물에 대해 고안된 예를 보았지만 실제로는 비즈니스 요구 사항이 변경되고 새로운 기능이 추가됨에 따라 실제로 “is-a”관계를 확장하기 전에 모든 작업을 수행하기가 어렵습니다. 새로운 요구 사항을 수용하기 위해 추가 기본 클래스 또는 인터페이스를 포함하도록 계층을 리모델링 / 리팩토링합니다. 오리 타이핑을 사용하면 모델링에 대해 걱정할 필요가 없습니다 . 필요한 기능 만 걱정 하면됩니다.

그러나 상속과 다형성은 매우 인기가 있기 때문에 확장 성 및 코드 재사용에 대한 지배적 전략이라고 부르는 것은 과장된 일이 아닙니다. 그렇다면 상속과 다형성이 왜 그렇게 성공적일까요? 상속 / 다형성이 오리 타이핑보다 더 큰 장점을 간과하고 있습니까?



답변

나는 대부분 당신에게 동의하지만, 재미를 위해 Devil ‘s Advocate를 할 것입니다. 명시 적 인터페이스는 형식적으로 무엇을해야하는지 알려주 는 명시적이고 공식적으로 지정된 계약 을 찾을 수있는 단일 장소를 제공합니다 . 프로젝트의 유일한 개발자가 아닌 경우에 중요 할 수 있습니다.

또한 이러한 명시 적 인터페이스는 오리 타이핑보다 더 효율적으로 구현할 수 있습니다. 가상 함수 호출은 인라인 할 수 없다는 점을 제외하고 일반 함수 호출보다 오버 헤드가 거의 없습니다. 오리 타이핑에는 상당한 오버 헤드가 있습니다. C ++ 스타일의 구조적 타이핑 (템플릿 사용)은 엄청난 양의 오브젝트 파일 팽창을 생성 할 수 있으며 (각 인스턴스화는 오브젝트 파일 레벨에서 독립적이므로) 컴파일 타임이 아닌 런타임에 다형성이 필요할 때 작동하지 않습니다.

결론 : Java 스타일 상속과 다형성이 PITA 일 수 있으며 대안을 더 자주 사용해야하지만 여전히 장점이 있음에 동의합니다.


답변

상속과 다형성은 특정 종류의 프로그래밍 문제에서 작동하기 때문에 널리 사용됩니다 .

그들이 학교에서 널리 배운 것이 아니라, 거꾸로 : 그들은 학교에서 널리 배웁니다. 사람들 (일명 시장)은 오래된 도구보다 더 잘 작동한다는 것을 알았 기 때문에 학교는 그들을 가르치기 시작했습니다. [일화 : OOP를 처음 배웠을 때 OOP 언어를 가르치는 대학을 찾는 것은 매우 어려웠습니다. 10 년 후, OOP 언어를 가르치지 않은 대학을 찾기가 어려웠습니다.]

당신은 말했다 :

다형성의 기본 개념은 함수를 한 번 작성하고 나중에 원래 함수를 변경하지 않고 프로그램에 새로운 기능을 추가 할 수 있다는 것입니다. 필요한 메소드를 구현하는 다른 파생 클래스를 작성하기 만하면됩니다.

내가 말하다:

아니, 그렇지 않아

당신이 묘사하는 것은 다형성이 아니라 상속입니다. OOP 문제가있는 것은 당연합니다! 😉

단계 백업 : 다형성은 메시지 전달의 이점입니다. 그것은 단순히 각 객체가 자신의 방식으로 메시지에 자유롭게 응답한다는 것을 의미합니다.

그래서 … 오리 타이핑이 있다 (또는 오히려, 수) 다형성

귀하의 질문의 요점은 OOP를 이해하지 못하거나 싫어한다는 것이 아니라 인터페이스 정의를 좋아하지 않는 것 같습니다 . 괜찮아요. 조심스럽게 일하면 잘 작동합니다. 단점은 실수를 한 경우 (예를 들어 방법을 생략 한 경우) 런타임까지는 알 수 없다는 것입니다.

이것은 정적 대 동적이며 Lisp만큼 오래된 토론이며 OOP에만 국한되지 않습니다.


답변

나는 객체들 사이의 연약한 관계 세트를 기반으로 불필요한 제한을 부과하는 것으로 상속과 다형성을 살펴보기 시작했습니다.

왜?

상속 (덕 타이핑 유무에 관계없이)은 공통 기능의 재사용을 보장합니다. 일반적인 경우 하위 클래스에서 일관되게 재사용 할 수 있습니다.

그게 다야. “불필요한 제한”은 없습니다. 단순화입니다.

마찬가지로 다형성은 “오리 타이핑”이 의미하는 것입니다. 같은 방법입니다. 인터페이스는 동일하지만 구현 방식이 다른 많은 클래스.

제한이 아닙니다. 단순화입니다.


답변

상속은 남용되지만 오리 타이핑도 마찬가지입니다. 둘 다 문제를 일으킬 수 있습니다.

강력한 타이핑을 사용하면 컴파일 타임에 많은 “단위 테스트”를 수행 할 수 있습니다. 오리 타이핑을 사용하면 종종 글을 써야합니다.


답변

학교에서 배우는 것의 장점 배우는 것입니다. 좋지 않은 것은 유용 할 때와 그렇지 않을 때를 이해하지 않고 조금 독단적으로 받아 들일 수 있다는 것입니다.

그런 다음, 독단적으로 배운다면, 나중에 다른 방향으로 독단적으로 “반란”할 수 있습니다. 그것도 좋지 않습니다.

그러한 아이디어와 마찬가지로 실용적인 접근 방식을 취하는 것이 가장 좋습니다. 자신이 맞는 곳과 그렇지 않은 곳에 대한 이해를 발전시킵니다. 그리고 그들이 과매도 된 모든 방법을 무시하십시오.


답변

예, 정적 입력 및 인터페이스는 제한 사항입니다. 그러나 구조화 된 프로그래밍이 발명 된 이후 (즉, “고토로 간주”) 모든 것이 우리를 제약하는 것이 었습니다. 밥 아저씨는 그의 비디오 블로그 에서 이것을 훌륭하게 받아 들였습니다 .

이제, 수축이 나쁘다고 주장 할 수 있지만, 반면에 그것은 매우 복잡한 주제에 질서, 통제 및 친숙 함을 가져옵니다.

다이나믹 한 타이핑과 심지어 직접 메모리 액세스를 도입함으로써 제약을 완화하는 것은 매우 강력한 개념이지만, 많은 프로그래머가 다루기가 더 어려워 질 수도 있습니다. 특히 프로그래머는 컴파일러에 의존하고 많은 작업을 위해 안전을 입력했습니다.


답변

상속은 두 클래스 사이의 매우 강력한 관계입니다. Java가 더 강하다고 생각하지 않습니다. 따라서 의미가있을 때만 사용해야합니다. 공개 상속은 “보통 is-a”가 아니라 “is-a”관계입니다. 상속을 과도하게 사용하고 혼란에 빠지기가 정말 쉽습니다. 많은 경우 상속은 “has-a”또는 “take-function-from-a”를 나타내는 데 사용되며 일반적으로 구성에 의해 더 잘 수행됩니다.

다형성은 “is-a”관계의 직접적인 결과입니다. Derived가 Base에서 상속되면 모든 Derived “is-a”Base이므로 Base를 사용하는 모든 위치에서 Derived를 사용할 수 있습니다. 상속 계층 구조에서 이것이 의미가 없다면 계층 구조가 잘못되어 상속이 너무 많을 수 있습니다.

오리 타이핑은 깔끔한 기능이지만 오용하려는 경우 컴파일러에서 경고하지 않습니다. 런타임에 예외를 처리하지 않으려면 매번 올바른 결과를 얻도록해야합니다. 정적 상속 계층을 정의하는 것이 더 쉬울 수 있습니다.

나는 정적 타이핑의 진정한 팬은 아니지만 (종종 조기 최적화의 한 형태라고 생각합니다) 일부 클래스의 오류를 제거하며 많은 사람들이 해당 클래스를 제거 할 가치가 있다고 생각합니다.

정적 타이핑 및 정의 된 상속 계층보다 동적 타이핑 및 덕 타이핑이 더 좋으면 괜찮습니다. 그러나 Java 방식에는 장점이 있습니다.