访问复合类的各个部分

时间:2011-05-18 13:29:09

标签: oop encapsulation pseudocode composition

我对组合和封装的概念感到困惑。

这是帮助我瓶颈的例子: 我有一个A类,它有B和C类的部分.B也有D和E类型的部分。

class A
{
   B itsB;
   C itsC;
}

class B
{
   D itsD;
   E itsE;
}

class D
{
   int mAlpha;
   int getAlpha();
   void setAplha(int);
}

A itsA;

对于这种情况,你如何只读访问mAlpha?

这样吗? itsA->getItsB()->getItsD()->getAlpha()

还是这样? itsA->getAlpha(),其中A::getAlpha()访问itsB->getItsD()->getAlpha()

写入访问mAlpha的方法怎么样?

这样吗? itsA->getItsB()->getItsD()->setAlpha(10.0)

还是这样? itsA->getItsB()->setAlpha(10.0),其中A::getAlpha()访问itsB->getItsD()->setAlpha(10.0)

所以问题是;访问/修改复合类的各个部分,同时遵守封装原则,你应该只通过复合类的接口访问吗?

否则,似乎您在没有所有者组合的知识/许可的情况下访问该部件,进行修改。

请帮助我摆脱这种混乱

感谢。

4 个答案:

答案 0 :(得分:0)

  

所以问题是;访问/修改复合类的各个部分,同时遵守封装原则,你应该只通过复合类的接口访问吗?

根据封装原理,应隐藏复合材料的部件。假设mAlpha在逻辑上是 A属性,但在{/ em> D中实现,则应在{{1}中添加访问者方法查找/更改其A部分中的mAlpha成员。否则,您将泄露D的实现细节(它是A和其他一些东西的组合。)

答案 1 :(得分:0)

我会让A通过公开自己相同的方法名称和签名来委托对getAlpha()的访问权。

class A
{
public:
    int getAlpha()
    {
        return itsB.getAlpha();
    }
};

class B
{
public:
    int getAlpha()
    {
        return itsD.getAlpha();
    }
};

虽然这会使代码变得复杂,但您应该考虑更改封装职责的方式。

答案 2 :(得分:0)

  

对于这种情况,你如何只读访问mAlpha?

     这样吗? itsA-> getItsB() - > getItsD() - > getAlpha()

     

还是这样? itsA-> getAlpha(),其中A :: getAlpha()访问其B-> getItsD() - > getAlpha()

这有点复杂,因为你必须尊重两种封装级别。 据推测,B被用作混合来实现A,因此您可能希望B成为A的私有成员,从而消除了第一种方法的可能性。第二种方式隐藏了A中B的存在,并且允许从A中实现一些合同,关于它允许对其进行B的操作。你可以在B和D之间将相同的事物分层,而不是只是提供一个指向D的指针并抓住Alpha视图,但是在B的实现中私下使用D。你最终会用相互调用的方法层,并且在简单的情况下它似乎效率低下,但它是关于什么是客户端A知道它的实现,以及B的客户知道B的实现。

从这个思想角度来看,你的第一行是写的,这样A的消费者必须知道它的内部结构才能获得Alpha值。它必须知道那里有一个带有Alpha的D。为了允许更改A的实现,您可以隐藏像getAlpha()这样的函数后面的细节。然后是B的同样的事情。

HTH

-Chris

答案 3 :(得分:0)

我将“封装”更多地作为一般概念。类具有多个字段,属性,方法,被视为单个项目,这些成员是公共的,私有的或受保护的。对于“封装”,对象是否包含其他对象并不重要。

class CarClass {
  private: double InitialPrice;
  protected: WheelClass wheels[4];
  protected: MotorClass motor;
  public: turnOn();
  public: turnOff();
}

这里,“封装”的意思是,让我们把这个字段,简单的数据类型或对象,这个方法,并将它们全部放到一个实体中。

对于“复合类”或“复合对象”,我将其作为对象,将其他对象作为其一部分。类或对象负责创建或销毁这些子元素对象。如果一个类有指针或引用其他对象,但它不负责删除或添加它们(在内存中分配),那么它不是复合的。

class SpaceShipClass {

  SpaceShipClass() {
   this.engine = new EngineClass();
   this.wings  = new WingClass();
  } 

  ~SpaceShipClass() {
   free this.engine();
   free this.wings();
  } 

  private: EngineClass engine; 
  protected: WingsClass wings; 
  public: PilotClass pilot; 

  public: Fly(); 
  public: Landing(); 
}

在前面的例子中,“引擎”& “翅膀”使“SpaceShipClass”成为复合类。但是,该领域的“飞行员”,并不是因为它不属于“类”,它只是有一个参考。

检查我没有使用类成员作用域(私有,受保护或公共)作为与“封装”或“组合”概念相关的内容,它是O.O.P.的一部分,但它不需要它用于封装或组合。事实上,有O.O.编程语言,其中所有成员都是公共的,并且仍然可以具有封装或组合类。

使用“参考”编程语言,使初学者更难理解“课堂作文”。