RealNumber 및 ComplexNumber 상속을 구현하는 방법은 무엇입니까?


11

학문적이지 않기를 바랍니다.

SW 라이브러리에 실수와 복소수가 필요하다고 가정 해 봅시다.

에 기초하는 것이다-A (또는 여기 ) 관계, 실제 번호는 A는 복소수의 허수 부분 B는 단순히 0 복소수.

반면에 내 구현은 자식이 부모를 확장하므로 부모 RealNumber에는 실제 부분이 있고 자식 ComplexNumber는 가상의 예술을 추가합니다.

또한 상속은 악하다 는 의견 있습니다.

교수는 어제처럼 대학에서 OOP를 배우고있을 때이 두 가지의 절대 값이 다르게 계산되기 때문에 상속의 좋은 예는 아니라고 회상했다. .

내 경험은 DRY를 해결하기 위해 종종 상속을 사용한다는 것입니다. 결과적으로 계층 구조에 인공 추상 클래스가 종종 있습니다 (실제 세계의 객체를 나타내지 않기 때문에 이름을 찾는 데 종종 문제가 있음).


7
이것은 이전 질문에서 다룬 것처럼 보입니다 : 사각형은 사각형에서 상속해야합니까?
gnat

1
@ gnat 오, 그게 내가 사용하고 싶은 또 다른 예였습니다 ... 감사합니다!
Betlista

7
... 수학 의미에서 "실수는 복소수"라는 문장은 불변의 숫자 에만 유효 하므로 불변의 객체를 사용하면 LSP 위반을 피할 수 있습니다 (정사각형과 직사각형의 경우에도 동일하게 유지됨) 그래서 대답하십시오 ).
Doc Brown

5
... 복소수에 대한 절대 값 계산은 실수에도 적용되므로 교수님의 의미가 확실하지 않습니다. 변경할 수없는 복소수로 "Abs ()"메서드를 올바르게 구현하고 그로부터 "실제"를 파생하면 Abs () 메서드는 여전히 올바른 결과를 제공합니다.
Doc Brown

답변:


17

수학적 의미에서 실수가 복소수이지만 복소수에서 실수를 도출하는 것은 좋은 생각이 아닙니다. 파생 클래스가 기본 클래스의 속성을 숨기면 안된다는 Liskov 대체 원칙에 위배됩니다.

이 경우 실수는 복소수의 허수 부분을 숨겨야합니다. 실제 부분 만 필요한 경우 숨겨진 부동 소수점 숫자 (가상 부분)를 저장하는 것은 의미가 없습니다.

이것은 기본적으로 주석에 언급 된 사각형 / 사각형 예제와 동일한 문제입니다.


2
오늘 나는이 "Liskow Substitution Principle"을 여러 번 보았습니다. 나는 그것을 모르기 때문에 그것에 대해 더 읽어야 할 것입니다.
Betlista

7
예를 들어 읽기 전용 방법을 통해 실수의 허수 부분을 0으로보고하는 것이 좋습니다. 그러나 허수가 허수가 0으로 설정되는 복소수로 실수를 구현하는 것은 의미가 없습니다. 이것은 상속이 오해의 소지가있는 경우입니다. 인터페이스 상속은 틀림없이 괜찮지 만 구현 상속은 디자인에 문제를 야기 할 것입니다.
amon

4
실수가 둘 다 불변 인 한, 실수가 복소수에서 상속되는 것이 완벽합니다. 오버 헤드는 신경 쓰지 않아도됩니다.
중복 제거기

@ 중복 제거기 : 흥미로운 점. 불변성은 많은 문제를 해결하지만이 경우 아직 완전히 확신하지 못합니다. 그것에 대해 생각해야합니다.
Frank Puffer

3

이 두 값의 절대 값이 다르게 계산되므로 상속의 좋은 예는 아닙니다.

이것은 실제로 모든 상속 에 대한 설득력있는 이유가 아니라 제안 된 class RealNumber<-> class ComplexNumber모델입니다.

당신은 합리적으로 인터페이스를 정의 할 수 있습니다 Number, 이는 모두 RealNumberComplexNumber구현합니다.

그처럼 보일 수 있습니다

interface Number
{
    Number Add(Number rhs);
    Number Subtract(Number rhs);
    // ... etc
}

그러나이 Number작업 의 다른 매개 변수를와 동일한 파생 유형으로 제한하고 싶을 this수 있습니다.

interface Number<T>
{
    Number<T> Add(Number<T> rhs);
    Number<T> Subtract(Number<T> rhs);
    // ... etc
}

또는 하위 유형 다형성 대신 구조적 다형성을 허용하는 언어를 사용합니다. 를 들어 특정 사건 번호 만 산술 연산자를 오버로드 할 수있는 기능을해야 할 수도 있습니다.

complex operator + (complex lhs, complex rhs);
complex operator - (complex lhs, complex rhs);
// ... etc

Number frobnicate<Number>(List<Number> foos, Number bar); // uses arithmetic operations

0

해결책 : 공개 RealNumber수업 이 없습니다

허수가 0 인 복잡한 숫자를 반환하는 ComplexNumber정적 팩토리 메소드 fromDouble(double)가 있다면 완전히 괜찮 습니다 . 그런 다음 RealNumberComplexNumber인스턴스 의 인스턴스에서 사용할 모든 작업을 사용할 수 있습니다 .

그러나 왜 당신이 공공 상속 RealNumber클래스 를 원할 것인지 / 왜 필요로하는지 알기가 어렵습니다. 일반적으로 상속은 이러한 이유로 사용됩니다 (내 머리에서, 일부를 놓친 경우 수정하십시오)

  • 행동을 확장. RealNumbers복소수로는 할 수없는 추가 연산을 수행 할 수 없으므로 아무 의미가 없습니다.

  • 특정 구현으로 추상 동작 구현. 때문에 ComplexNumber추상적 인 안이 또한 적용되지 않습니다.

  • 코드 재사용. ComplexNumber클래스를 사용하는 경우 코드의 100 %를 재사용하십시오.

  • 특정 작업에 대해보다 구체적이고 효율적이며 정확한 구현. 이것은 여기에 적용될 수 있으며 RealNumbers일부 기능을 더 빨리 구현할 수 있습니다 . 그러나이 서브 클래스는 정적 뒤에 숨겨져 fromDouble(double)있고 외부에 알려서는 안됩니다. 이렇게하면 가상 부분을 숨길 필요가 없습니다. 외부의 경우 복소수 (실수) 만 있어야합니다. 실수로 이어지는 복소수 클래스의 모든 조작에서이 개인 RealNumber 클래스를 리턴 할 수도 있습니다. (이것은 클래스가 대부분의 숫자 클래스로 변경할 수 없다고 가정합니다.)

그것은 0이라고하는 Integer의 서브 클래스를 구현하는 것과 같으며 일부 조작은 영 (0)에 사소한 것이므로 하드 코딩합니다. 모든 0은 정수이므로 이것을 수행 할 수 있지만 공개하지는 마십시오.


증명할 소스가 없기 때문에 공감대를 얻는 것이 놀랍지 않습니다. 또한 아무도 다른 아이디어가 없다면 항상 그 이유가 있다고 생각합니다. 그러나 왜 잘못 생각하고 어떻게 더 나아질 수 있는지 알려주십시오.
findusl

0

실수가 복소수라고 말하는 것은 컴퓨터 과학보다 수학, 특히 이론에서 더 의미가 있습니다.
수학에서 우리는 말합니다 :

  • 복소수 세트에는 실수 세트가 포함되므로 실수는 복소수입니다.
  • 유리수 세트는 유리수 세트 (및 비이성 수 세트)를 포함하기 때문에 유리수는 실수입니다.
  • 합리적인 숫자 세트에는 정수 세트가 포함되므로 정수는 합리적인 숫자입니다.

그러나 이것이 RealNumber 및 ComplexNumber 클래스를 포함하도록 라이브러리를 설계 할 때 상속을 사용해야하거나 심지어 상속해야한다는 의미는 아닙니다. 에서 효과적인 자바 Second Edition의 조슈아 블로흐; 항목 16은 "상속적인 선호 구성"입니다. 해당 항목에서 언급 된 문제를 피하기 위해 RealNumber 클래스를 정의한 후에는 ComplexNumber 클래스에서 사용할 수 있습니다.

public class ComplexNumber {
    private RealNumber realPart;
    private RealNumber imaginaryPart;

    // Implementation details are for you to write
}

이를 통해 Joshua Bloch가 식별 한 문제를 피하면서 RealNumber 클래스를 재사용하여 코드를 DRY로 유지할 수 있습니다.


0

여기에는 두 가지 문제가 있습니다. 첫 번째는 컨테이너 유형과 내용 유형에 대해 같은 용어를 사용하는 것이 일반적이며, 특히 숫자와 같은 기본 유형과 동일합니다. double예를 들어, 용어 는 배정 밀도 부동 소수점 값과 값이 저장 될 수있는 컨테이너를 설명하는 데 사용됩니다.

두 번째 문제는 is-a는 다양한 유형의 객체를 읽을 수있는 컨테이너 간의 관계가 객체 자체 간의 관계와 동일하게 동작하는 반면, 다양한 유형의 객체를 배치 할 수있는 컨테이너 간의 관계는 해당 컨텐츠의 내용과 반대되는 동작입니다. . 인스턴스를 보유하는 것으로 알려진 모든 케이지는의 인스턴스 Cat를 보유하는 케이지 Animal이지만 의 인스턴스를 보유하는 케이지 일 필요는 없습니다 SiameseCat. 반면, 모든 인스턴스를 보유 할 수있는 모든 케이지는 모든 인스턴스를 보유 Cat할 수있는 케이지 SiameseCat이지만 의 모든 인스턴스를 보유 할 수있는 케이지 일 필요는 없습니다 Animal. 모든 인스턴스를 보유 Cat할 수 있고 보장 할 수있는 유일한 케이지 는 인스턴스 이외의 다른 것을 보유하지 않습니다.Cat의 케이지입니다 Cat. 다른 종류의 케이지는 수용 Cat해야하는 일부 사례 를 수용 할 수 없거나의 사례가 아닌 것을 수용 할 수있다 Cat.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.