5

我正在为考试而学习,并试图弄清楚这个问题。具体问题是“继承和对象组合都促进代码重用。(T/F)”,但我相信我理解问题的继承部分。

我相信继承促进了代码重用,因为类似的方法可以放在抽象基类中,这样类似的方法就不必在多个子类中以相同的方式实现。例如,如果你有三种形状,并且每种形状的方法“getName”只是返回一个数据成员“_name”,那么当它可以在抽象基中实现一次时,为什么要在每个子类中重新实现这个方法类“形状”。

但是,我对对象组合的最佳理解是对象/类之间的“具有”关系。例如,一个学生有一所学校,一个学校有许多学生。这可以看作是对象组合,因为没有彼此它们就不能真正存在(没有任何学生的学校不完全是一所学校,是吗?等等)。但是我认为这两个对象“拥有”彼此作为数据成员不会促进代码重用。

有什么帮助吗?谢谢!

4

5 回答 5

5

对象组合可以促进代码重用,因为您可以将实现委托给不同的类,并将该类作为成员包含在内。

您可以创建具有更小范围和更小的方法的更小的类,并在整个代码中重用这些类/方法,而不是将所有代码放在最外层类的方法中。

class Inner
{
public:
    void DoSomething();
};

class Outer1
{
public:
    void DoSomethingBig()
    {
        // We delegate part of the call to inner, allowing us to reuse its code
        inner.DoSomething();
        // Todo: Do something else interesting here
    }

private:
    Inner inner;
};

class Outer2
{
public:
    void DoSomethingElseThatIsBig()
    {
        // We used the implementation twice in different classes,
        // without copying and pasting the code.

        // This is the most basic possible case of reuse

        inner.DoSomething();

        // Todo: Do something else interesting here
    }


private:
    Inner inner;
};

正如您在问题中提到的,这是两个最基本的面向对象编程原则之一,称为“有关系”。继承是另一种关系,称为“is-a relationship”。

您还可以以非常有用的方式将继承和组合结合起来,这通常会增加您的代码(和设计)重用潜力。任何现实世界和架构良好的应用程序都会不断地将这两个概念结合起来,以获得尽可能多的重用。当您了解设计模式时,您会发现这一点。

编辑:

根据 Mike 在评论中的要求,一个不太抽象的例子:

// Assume the person class exists

#include<list>

class Bus
{
public:
    void Board(Person newOccupant);
    std::list<Person>& GetOccupants();

private:
    std::list<Person> occupants;
};

在此示例中,您没有重新实现链表结构,而是将其委托给列表类。每次使用该列表类时,您都在重新使用实现该列表的代码。

事实上,由于列表语义是如此普遍,C++ 标准库给了你std::list,你只需要重用它。

于 2011-08-02T01:37:11.107 回答
3

我必须同意@Karl Knechtel - 这是一个非常糟糕的问题。正如他所说,很难解释为什么,但我会试一试。

第一个问题是它使用了一个没有定义的术语——“代码重用”对不同的人意味着很多不同的东西。对某些人来说,剪切和粘贴相当于代码重用。只要我喜欢它,我必须同意他们,至少在某种程度上。其他人以排除剪切和粘贴的方式将代码重用定义为代码重用(将相同代码的另一个副本分类为单独的代码,而不是重用相同的代码)。我也可以看到这种观点,尽管我倾向于认为它们的定义更多地是为了特定目的而不是真正有意义(即,“代码重用”-> 好,“剪切-粘贴”-> 不好,因此“剪切-粘贴”!=“代码重用”)。不幸的是,我们在这里看到的就在边界上,

您的教授使用的定义可能在很大程度上取决于他对 OOP 的热情程度——尤其是在 90 年代(左右)当 OOP 刚刚成为主流时,许多人选择以仅包括很酷的新 OOP“东西”。要实现代码重用的必杀技,您不仅要注册他们的 OOP 信仰,而且要真正相信它!像作曲这样平凡的东西不可能有资格——无论他们多么奇怪地扭曲了语言才能做到这一点。

作为第二个要点,在使用 OOP 数十年之后,一些人已经对哪些代码被重用和哪些没有被重用做了一些相当仔细的研究。我见过的大多数都得出了一个相当简单的结论:很难(即,基本上不可能)将编码风格与重用联系起来。几乎所有你试图制定的关于什么会或不会导致代码重用的规则都可以并且将经常被违反。

第三,我怀疑在许多人的心目中往往是最重要的事实是,提出这个问题听起来好像这是可以/将会影响典型编码器的东西——你可能想要在组合和继承(例如)基于哪个“促进代码重用”更多,或者按照该顺序。现实情况是(仅举例来说)您应该在组合和继承之间进行选择,主要基于哪个更准确地模拟您要解决的问题以及哪个更能帮助您解决该问题。

虽然我没有任何严肃的研究来支持这一论点,但我认为该代码被重用的机会将在很大程度上取决于在大多数研究中甚至很少考虑的几个因素:1)某人的问题有多相似else 需要解决,以及 2)他们是否认为让你的代码适应他们的问题比编写新代码更容易。

我应该补充一点,在我看到的一些研究中,发现了一些似乎影响代码重用的因素。据我所知,最重要/最能说明问题的根本不是代码本身,而是该代码可用的文档。能够在基本上不进行逆向工程的情况下使用代码,这对代码的重用做出了很大贡献。第二点只是代码的质量——许多研究是在他们试图促进代码重用的地方/情况下完成的。在相当多的案例中,人们尝试重用比实际更多的代码,但不得不放弃它,只是因为代码不够好——从错误到笨拙的接口到糟糕的可移植性,一切都阻碍了重用。

简介: 我将继续记录在案,至少在过去的几十年中,代码重用可能是软件工程中最被夸大、未能兑现的承诺。即使充其量,代码重用仍然是一个相当难以实现的目标。试图将其简化到基于两个因素将其视为真/假问题的程度,将问题过于简单化,以至于它不仅毫无意义,而且完全荒谬。它似乎轻视和贬低了几乎整个软件工程实践。

于 2011-08-02T04:52:41.617 回答
3

1)学生知道一所学校,但这并不是真正的HAS-A关系;虽然您想跟踪学生就读的学校,但将学校描述为学生的一部分是不合逻辑的。

2)更多的人占据学校,而不仅仅是学生。这就是重用的用武之地。每次描述一种新型的学校参与者时,您不必重新定义构成学校的事物。

于 2011-08-02T01:34:15.553 回答
2

我有一个对象 Car 和一个对象 Engine:

class Engine {
     int horsepower;
}

class Car {
     string make;
     Engine cars_engine;
}

汽车有引擎;这是组合。但是,我不需要重新定义引擎来将引擎放入汽车中——我只是说汽车有引擎。因此,组合确实促进了代码重用。

于 2011-08-02T01:31:57.643 回答
2

对象组合确实促进了代码重用。如果没有对象组合,如果我正确理解了您对它的定义,那么每个类都只能有原始数据成员,这将是非常糟糕的。

考虑类

class Vector3
{
    double x, y, z;
    double vectorNorm;
}

class Object
{

    Vector3 position;
    Vector3 velocity;
    Vector3 acceleration;
 }

如果没有对象组合,您将被迫拥有类似的东西

class Object
{

    double positionX, positionY, positionZ, positionVectorNorm;
    double velocityX, velocityY, velocityZ, velocityVectorNorm;
    double accelerationX, accelerationY, accelerationZ, accelerationVectorNorm;
 }

这只是一个非常简单的例子,但我希望你能看到即使是最基本的对象组合也是如何促进代码重用的。现在想想如果 Vector3 包含 30 个数据成员会发生什么。这回答了你的问题了吗?

于 2011-08-02T01:38:34.200 回答