문제

프로젝트에서 우리 팀은 객체 목록을 사용하여 모두 유사한 방식으로 처리되어야 하는 데이터 세트에 대해 대량 작업을 수행하고 있습니다.특히 서로 다른 객체는 이상적으로 동일하게 작동하며 이는 다형성을 통해 매우 쉽게 달성됩니다.내가 가진 문제는 상속이 관계보다는 가지고있다 관계.예를 들어 여러 객체 가지고있다 손상 카운터를 개체 목록에서 쉽게 사용할 수 있도록 하기 위해 다형성을 사용할 수 있습니다. 사실이 아닐 것 같은 관계.(사람 는 아니다 피해 카운터.)

내가 생각할 수 있는 유일한 해결책은 상속에 의존하는 대신 암시적으로 캐스팅될 때 클래스 멤버가 적절한 개체 유형을 반환하도록 하는 것입니다.포기하는 것이 낫지 않을까? / 가지고있다 프로그래밍 용이성에 대한 대가로 이상적입니까?

편집하다:좀 더 구체적으로 말하자면, 저는 C++를 사용하고 있습니다. 따라서 다형성을 사용하면 파생 클래스가 단일 목록 내에 상주할 수 있고 기본 클래스의 가상 함수에 의해 작동될 수 있다는 의미에서 다양한 객체가 "동일하게 작동"할 수 있습니다.인터페이스를 사용하는 것(또는 상속을 통해 인터페이스를 모방하는 것)은 제가 기꺼이 사용할 솔루션인 것 같습니다.

도움이 되었습니까?

해결책

이는 다중 상속을 사용하여 수행할 수 있습니다.특정 경우(C++)에서는 순수 가상 클래스를 인터페이스로 사용할 수 있습니다.이를 통해 범위/모호성 문제를 일으키지 않고 다중 상속을 가질 수 있습니다.예:

class Damage {
    virtual void addDamage(int d) = 0;
    virtual int getDamage() = 0;
};

class Person : public virtual Damage {
    void addDamage(int d) {
        // ...
        damage += d * 2;
    }

    int getDamage() {
        return damage;
    }
};

class Car : public virtual Damage {
    void addDamage(int d) {
        // ...
        damage += d;
    }

    int getDamage() {
        return damage;
    }
};

이제 Person과 Car 모두 'is-a' Damage입니다. 즉, Damage 인터페이스를 구현합니다.순수 가상 클래스(인터페이스와 유사)를 사용하는 것이 핵심이며 자주 사용해야 합니다.이는 전체 시스템 변경으로 인한 향후 변경 사항을 방지합니다.자세한 내용은 개방-폐쇄 원칙을 읽어보세요.

다른 팁

내 생각에는 인터페이스를 구현하여 구현해야 한다고 생각합니다. 가지고있다 관계(이 작업은 C#에서 수행하고 있습니다):

public interface IDamageable
{
    void AddDamage(int i);
    int DamageCount {get;}
}

객체에서 이를 구현할 수 있습니다.

public class Person : IDamageable

public class House : IDamageable

그리고 DamageCount 속성에는 사람과 집이 일종의 계층 구조로 서로 관련되어 있음을 암시하지 않고 피해를 추가할 수 있는 방법이 있다는 것을 확신할 수 있습니다.

Jon의 말에 동의합니다. 하지만 여전히 별도의 손상 카운터 클래스가 필요하다고 가정하면 다음을 수행할 수 있습니다.

class IDamageable {
  virtual DamageCounter* damage_counter() = 0;
};
class DamageCounter {
  ...
};

각 손상 가능 클래스는 자체적인 Damage_counter() 멤버 함수를 제공해야 합니다.이것의 단점은 손상 가능한 각 클래스에 대해 vtable을 생성한다는 것입니다.대신 다음을 사용할 수 있습니다.

class Damageable {
 public:
  DamageCounter damage_counter() { return damage_counter_; }
 private:
  DamageCounter damage_counter_;
};

그러나 많은 사람들은 쿨하지 않아 여러 부모가 멤버 변수를 가질 때 다중 상속이 가능합니다.

때로는 현실을 위해 이상을 포기하는 것이 가치가 있습니다.실질적인 이익 없이 "제대로 하는 것"이 ​​큰 문제를 야기한다면, 나는 그 일을 잘못할 것입니다.불필요한 다중 상속으로 인해 복잡성이 증가하고 ~할 수 있다 시스템 유지 관리가 덜 어려워지는 데 기여합니다.상황에 따라 무엇이 최선인지 결정해야 합니다.

한 가지 옵션은 이러한 객체가 Damageable 인터페이스를 상속받는 것이 아니라 DamageCounter.이로써 사람이 가지고있다 데미지 카운터, 하지만 ~이다 손상 가능.(저는 인터페이스가 명사보다 형용사로서 훨씬 더 의미가 있다는 것을 종종 발견합니다.) 그러면 일관된 손상 인터페이스를 가질 수 있습니다. Damageable 손상 카운터가 기본 구현임을 노출하지 않습니다(필요한 경우는 제외).

템플릿 경로(C++ 또는 유사한 가정)로 가고 싶다면 믹스인을 사용하여 이 작업을 수행할 수 있지만 잘못 수행하면 정말 빨리 추악해질 수 있습니다.

이 질문은 정말 혼란스럽습니다 :/

굵게 표시된 귀하의 질문은 매우 개방적이며 "상황에 따라 다릅니다"라는 답변이 있지만 귀하의 예는 귀하가 요청하는 맥락에 대해 실제로 많은 정보를 제공하지 않습니다.이 대사는 나를 혼란스럽게 한다.

모두 비슷한 방식으로 처리되어야 하는 데이터 세트

어떤 방법으로?세트가 함수에 의해 처리됩니까?다른 수업?데이터에 대한 가상 기능을 통해?

특히 서로 다른 객체는 이상적으로 동일하게 작동하며 이는 다형성을 통해 매우 쉽게 달성됩니다.

"동일하게 행동하는 것"이라는 이상과 다형성은 전혀 관련이 없습니다.다형성을 사용하면 어떻게 이를 쉽게 달성할 수 있나요?

@케빈

일반적으로 'is a'와 'has a'에 대해 이야기할 때 상속과 구성에 대해 이야기합니다.

음... 손상 카운터는 파생 클래스 중 하나의 속성일 뿐이며 귀하의 질문과 관련하여 '사람은 손상 카운터입니다'라는 측면에서 실제로 논의되지 않습니다.

피해 카운터를 속성으로 갖는다고 해서 피해 카운터가 있는 다양한 개체를 컬렉션으로 만들 수는 없습니다.예를 들어, 사람과 자동차 모두 손상 카운터를 가질 수 있지만 손상 카운터를 가질 수는 없습니다. vector<Person|Car> 또는 vector<with::getDamage()> 또는 대부분의 언어에서 유사한 것.공통 Object 기본 클래스가 있는 경우 그런 식으로 밀어넣을 수는 있지만 해당 클래스에 액세스할 수는 없습니다. getDamage() 일반적으로 방법.

내가 읽은 바에 따르면, 그것이 그의 질문의 핵심이었습니다."위반해야 하나? is-a 그리고 has-a 특정 사물이 동일하지 않음에도 불구하고 동일한 것처럼 취급하기 위해?"

일반적으로 'is a'와 'has a'에 대해 이야기할 때 상속과 구성에 대해 이야기합니다.

음... 손상 카운터는 파생 클래스 중 하나의 속성일 뿐이며 귀하의 질문과 관련하여 '사람은 손상 카운터입니다'라는 측면에서 실제로 논의되지 않습니다.

이것 좀 봐:

http://www.artima.com/designtechniques/compoinh.html

그 과정에서 도움이 될 수 있습니다.

@데릭:문구에서 나는 거기에 가정 ~였다 기본 클래스, 질문을 다시 읽은 후 이제 그가 무엇을 얻고 있는지 알 수 있습니다.

"제대로 하는 것"은 장기적으로 이익이 될 것입니다. 왜냐하면 나중에 시스템을 유지 관리하는 사람이 시스템이 처음부터 올바르게 수행되었는지 이해하기가 더 쉬울 것이기 때문입니다.

언어에 따라 다중 상속 옵션이 있을 수도 있지만 일반적으로 간단한 인터페이스가 가장 적합합니다."단순하다"는 것은 너무 과하지 않은 인터페이스를 만드는 것을 의미합니다.간단한 인터페이스가 많고 모놀리식 인터페이스가 몇 개 있는 것이 더 좋습니다.물론, 항상 절충안이 있으며 인터페이스가 너무 많으면 인터페이스에 대해 "잊혀질" 수 있습니다.

@앤드류

"동일하게 행동하는 것"이라는 이상과 다형성은 전혀 관련이 없습니다.다형성을 사용하면 어떻게 이를 쉽게 달성할 수 있나요?

예를 들어 그들은 모두 하나의 공통된 기능을 가지고 있습니다.그것을 부르자 addDamage().다음과 같은 작업을 수행하려는 경우:

foreach (obj in mylist)
    obj.addDamage(1)

그런 다음 동적 언어가 필요하거나 공통 상위 클래스(또는 인터페이스)에서 확장하기 위해 필요합니다.예:

class Person : DamageCounter {}
class Car : DamageCounter {}

foreach (DamageCounter d in mylist)
    d.addDamage(1)

그러면 치료가 가능합니다 Person 그리고 Car 매우 유용한 상황에서도 마찬가지입니다.

다형성 상속이 필요하지 않습니다.다형성은 여러 개체가 동일한 메시지 서명(메서드)을 구현할 때 얻게 되는 것입니다.

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