代码之家  ›  专栏  ›  技术社区  ›  Cristián Romo

遗传和多态性-易用性与纯度

  •  5
  • Cristián Romo  · 技术社区  · 18 年前

    关系,而不是 关系例如,几个对象 损坏计数器,但为了便于在对象列表中使用,可以使用多态性-除非这意味着 不可能是真的关系。(A)某人 损坏计数器。)

    我能想到的唯一解决方案是让类的成员在隐式强制转换时返回正确的对象类型,而不是依赖继承。放弃这个计划会更好吗 是一个 有一个

    编辑: 更具体地说,我使用C++,所以使用多态性将允许不同的对象在“派生类可以驻留在单个列表中并由基类的虚拟函数操作”的意义上“动作相同”。使用接口(或通过继承模仿接口)似乎是我愿意使用的解决方案。

    10 回复  |  直到 18 年前
        1
  •  5
  •   Jon Limjap    18 年前

    我认为您应该实现接口,以便能够执行 有一个 关系(我用C#做这件事):

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

    您可以在对象中实现这一点:

    public class Person : IDamageable
    
    public class House : IDamageable
    

        2
  •  3
  •   Brian    18 年前

    这可以通过使用多重继承来实现。在特定情况下(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;
        }
    };
    

    现在人和车都是“a”损坏,也就是说,他们实现了损坏接口。使用纯虚拟类(使它们类似于接口)是关键,应该经常使用。它将未来的变化与改变整个系统隔离开来。更多信息,请阅读开闭原理。

        3
  •  1
  •   0124816    18 年前

    我同意Jon的观点,但假设您仍然需要一个单独的伤害计数器类,您可以:

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

    然后,每个可损坏类都需要提供自己的损坏计数器()成员函数。这样做的缺点是,它会为每个可损坏的类创建一个vtable。您可以改为使用:

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

    但很多人都是这样

        4
  •  0
  •   Derek Park    18 年前

    有时候,为了现实而放弃理想是值得的。如果“做对了”而没有真正的好处会导致一个巨大的问题,那么我会做错。话虽如此,我经常认为花时间把它做好是值得的,因为不必要的多重继承增加了复杂性,而且 可以

    Damageable 接口,而不是从 DamageCounter . 这样,一个人 损坏计数器,但是 可损坏的。(我经常发现界面作为形容词比作为名词更有意义。)然后你可以有一个一致的界面 对象,而不公开损坏计数器是底层实现(除非需要)。

    如果你想走模板路径(假设C++或类似的),你可以用Mixin来做,但是如果做得不好,它会很快变丑。

        5
  •  0
  •   Andrew Grant    18 年前

    这个问题实在令人困惑:/

    你的粗体问题非常开放,答案是“视情况而定”,但你的例子并没有给出很多关于你提问的背景的信息。这些台词让我困惑;

    应以类似方式处理的数据集

    怎么走?集合是否由函数处理?另一节课?通过数据上的虚拟函数?

    特别是,不同的对象在理想情况下的行为是相同的,这很容易通过多态性实现

    “一模一样”的理想和多态性是完全不相关的。多态性如何使其易于实现?

        6
  •  0
  •   Community Mohan Dere    6 年前

    嗯…伤害计数器只是一个派生类的属性,不会在你的问题中用“人就是伤害计数器”来讨论。

    将伤害计数器作为属性不允许他将具有伤害计数器的不同对象放入集合中。例如,一个人和一辆车可能都有损坏计数器,但您不能有损坏计数器 vector<Person|Car> vector<with::getDamage()> 或者在大多数语言中类似的东西。如果您有一个公共对象基类,那么您可以用这种方式推送它们,但是您不能访问 getDamage()

    is-a 和 has-a 为了将某些对象视为相同的对象,即使它们不是?”

        7
  •  0
  •   Community Mohan Dere    9 年前

    通常,当我们谈论“是”时,有一个“是”和“是”,我们谈论的是继承和组合。

    见此:

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

    Derek 是

        8
  •  0
  •   Andrew    18 年前

    从长远来看,“正确操作”将带来好处,如果只是因为以后维护系统的人会发现,如果一开始就正确操作,就更容易理解。

    根据语言的不同,您可以选择多重继承,但通常简单的接口最有意义。我所说的“简单”是指制作一个不太复杂的界面。最好有很多简单的接口和几个单片接口。当然,总是有一个折衷,太多的接口可能会导致被“遗忘”的接口。。。

        9
  •  0
  •   Derek Park    18 年前

    @安德鲁

    “一模一样”的理想和多态性是完全不相关的。多态性如何使其易于实现?

    addDamage()

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

    然后,您需要一种动态语言,或者需要它们从公共父类(或接口)扩展。例如。:

    class Person : DamageCounter {}
    class Car : DamageCounter {}
    
    foreach (DamageCounter d in mylist)
        d.addDamage(1)
    

    那么,你可以请客了 Person 和 Car 在某些非常有用的情况下也是如此。

        10
  •  0
  •   Steven A. Lowe    16 年前

    多态性 不需要继承