공통 필드를 기본 클래스로 이동하는시기


16

저는 현재 두 개의 파생 클래스를, A그리고 B모두가 공통으로 필드를 가지고 있고 그것이 기본 클래스에 올라가 여부를 결정하기 위해 노력하고 있음.

이것은 기본 클래스에서 참조하지 않고, 다른 클래스가 파생 길 아래에 어떤 시점에서, 경우에 말을 결코 C, 그건이없는 _field1"최소 특권"(또는 무언가)의 주요되지는 경우에 위반 될 다음, 였다?

public abstract class Base
{
    // Should _field1 be brought up to Base?
    //protected int Field1 { get; set; }
}

public class A : Base
{
    private int _field1;
}

public class B : Base
{
    private int _field1;
}

public class C : Base
{
    // Doesn't have/reference _field1
}

18
당신이 우리에게 무엇을 어떤 생각 부여하지 않았기 때문에 나는이 질문이 명확하지 않다 생각 Base, A, B, C, 그리고 _field1됩니다. 이것들은 생략해서는 안되는 중요한 세부 사항입니다. 질문이 무엇인지 이야기하기 위해 질문을 편집해야한다고 생각합니다.
Tanner Swett

대답에 따라 가상 서스펜션을 갖도록 차량을 재 구축하면 자동차와 자전거에 바퀴가 있고 보트에 부력이 생겨 추상화가 위로 올라갑니다. 내 추상화가 특정 설정으로 직접 연결되면 개념을 체인 위로 충분히 옮기지 않았습니다.
Patrick Hughes

6
코드 중복을 피하기 위해 클래스 상속을 사용하지 마십시오. 다형성 과 같은 행동 을 상속하고 확장하는 데 사용하십시오 . 논리적으로 동일한 필드 인 경우에만 공통 필드를 기본 클래스로 이동 하십시오. 각 컨텍스트에서 동일한 이름을 공유하는 두 개의 관련되지 않은 정보는 아닙니다.
Brandon

왜 기본 수업을 시작해야합니까?
jpmc26

답변:


34

그것은 모두 해결하려는 정확한 문제에 달려 있습니다.

구체적인 예를 고려하십시오. 추상 기본 클래스는 Vehicle현재 있으며 구체적인 구현은 BicycleCar입니다. 차량 이동 numberOfWheels을 고려 Bicycle하고 Car있습니다. 이렇게해야합니까? 아니! 모든 차량에 바퀴가있는 것은 아닙니다. Boat클래스 를 추가 하려고하면 중단 될 것이라고 이미 알 수 있습니다 .

이제 추상 기본 클래스가 있다면 멤버 변수 WheeledVehicle를 갖는 것이 논리적 numberOfWheels입니다.

보시다시피 간단한 예 또는 대답이 아니기 때문에 문제에 동일한 논리를 적용해야합니다.


3
0이 유효한 numberOfWheels임을 일시적으로 승인 할 수 있습니다. 그러나 결국 roll()에는 하위 클래스 아이디어가 예전처럼 보이는 시점에 메소드를 추가 할 수 있습니다 .
user949300

11
보트에는 바퀴가 0 개 있습니다. 그게 뭐야?
D Drmmr

14
@DDrmmr 보트에는 바퀴가 0 개가 아니라 바퀴가 보트의 개념으로 존재하지 않기 때문에 모델에서 허용하지 않아야합니다.
Peter M

10
내 요점은 예가 나쁘다는 것입니다. 바퀴가 0 개라는 차량 (보트 인 경우)에는 개념 상 문제가 없습니다.
D Drmmr

10
그런 다음 패들 보트를 보관해야 할 때 모두 지옥에 빠집니다.
IllusiveBrian

13

논리적으로 말하자면, 서브 클래스에서 복제 된 필드를 기본 클래스에서 공통으로 배치하는 것 외에도 세 번째 옵션이 있습니다.이 옵션은 새로운 서브 클래스를 계층 구조에 도입하여 둘 사이에 공통 속성이 있습니다. @Pete는 완전히 거기에 가지 않고 이것을 암시합니다.

@Pete의 예제를 사용하여, 원래의 기본 클래스에서 내려 오는 Wheeled Vehicle에 대한 (아마도 추상적 인) 서브 클래스를 소개합니다. 반면에 두 개의 서브 클래스는 그 하위 클래스입니다. 따라서 원래 기본 클래스는 휠로 오염되지 않지만 휠의 공통성은 DRY입니다 (휠이있는 서브 클래스에서는 반복되지 않음).

물론 이것은 당신의 목적을 위해 과잉 일 수 있지만 클래스 계층 구조 메커니즘에 의해 지원됩니다.


이것은 실제로 내가하기로 결정한 것입니다 (A와 B가 대부분 겹치므로 B는 A에서 파생됩니다).
samis

9

나는 여기서 악마의 옹호자를 할 것입니다.

지금 당장은 아무 것도 하지 말아야 합니다.

건조합니까? 아니요. 그러나 나중에 쉽게 되돌릴 수없는 조기 추상화보다 약간 중복하는 것이 좋습니다. 속성을 공통 기본 클래스로 이동하는 리 팩터는 쉽습니다. 다른 방법으로가는 것은 아닙니다. 기다려 봐

이런 종류의 결정을 내릴 때 나는 "3의 규칙"을 사용하는 경향이 있습니다. 예를 들어 3 개의 다른 장소에서 같은 것을 반복 한 후에 만 ​​체인 위로 옮기는 것을 고려하십시오. NB는 2에 불과합니다.


2
결정을 내리기 위해서는 현명한 관찰이 필요합니다.
radarbob

1
나는 대부분 동의하지만, "지금 바로"(우리가 보는 것과 같은 추가 코드가 없음) 양방향 리팩토링은 사소한 것입니다. 그러나 필드를 사용하는 추가 코드가 있으면 양방향 리팩토링 이 훨씬 어려워 질 수 있습니다.
Doc Brown

2

일반적으로 나는 그것을 기본 수업으로 옮길 것입니다. 나는 사용하지 않는 필드를 운반하는 것과 복잡성을 감소시키는 트레이드 오프가 있기 때문에 그렇다는 목표가 있다고 생각하지 않습니다.

나는 일반적으로 공유 할 수있는 것을 포함하는 '무거운'기본 클래스를 선호합니다. 이렇게하면 파생 된 모든 클래스에서 하위 직렬화 메서드가 필요하지 않기 때문에 파일 직렬화가 더 간단 해집니다. 그러나 그와 비슷한 문제가 없거나 메모리 사용을 줄이기 위해 가능한 모든 작업을 수행 해야하는 경우 필요한 필드 만 유지하면됩니다.

필드 수가 매우 제한적인 경우 공통 필드를 소개하는 '중개'클래스가 좋습니다. 그러나 서로 다른 조합으로 수십 개의 필드를 사용하는 경우 접근 방식이 복잡성을 크게 증가시켜 각각의 특정 필드 집합을 도입하는 많은 중개 클래스가 생길 수 있습니다. 유지 관리 문제가 될 수 있습니다.


내 예제는 사소한 것이지만 여전히 프로덕션 코드입니다. "무거운"기본 클래스를 사용하여 계층 구조를 "손상"시키는 데 대해 좋은 주장을합니다.
samis

1
@samis : 프로덕션 코드에 하나의 필드 만 있고 메소드가없는 "A, B, C"및 "Base"라는 클래스를 사용하십니까? 나는 질문한다.
Doc Brown
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.