1

所以可以说我有一个由其他类组成的类。

class HttpRequest
{
public $session = new Session();
// .. the rest of the HttpRequest code
}

现在,我想通过 HttpRequest 类访问 Session 类,所以我使用组合。但这是否违反了 OOP 封装或数据隐藏的规定,即所有属性都应该受到保护,并通过 setter 和 getter 方法访问?

这是错的吗:

$request = new HttpRequest();
$request->session->set('id', 5);

或者我应该使用这个:

$request = new HttpRequest();
$session = $request->getSession();
$session->set('id', 5);

封装状态应该保护属性。那么如何提供对内部类的访问呢?就正确的 OOP 而言,第一个示例是否错误?

4

3 回答 3

1

不允许直接访问对象的正当理由:

  • 允许在对象本身之外对对象进行操作。如果您公开该属性,您的代码的任何部分都可能覆盖 HttpRequest 类上的 $session,并且您将很难跟踪它。从数据保护的角度来看,封装是为了确保只有对象的方法可以直接改变对象。
  • 允许您优雅地处理未设置该变量的情况。如果由于某种原因, $session 没有在你的类上设置 - 当你尝试调用它的方法时,你会立即遇到致命错误。如果将它包装在 getter 中,则可以检查该条件并动态创建该类的新实例。
  • 遵循真正的“OO”范式

但是,在某些情况下,我会说这样做是可以的。特别是如果您知道该属性将始终被设置(并且不会设置它的唯一方式是不支持使用该对象的方式)。

这也取决于如何访问该属性。Symfony2 在他们的 Request 类中使用了这个。在这种情况下感觉很自然,因为“查询”、“发布”和“请求”变量都是“参数包”(美化数组)。但是,它们确实为 Session 对象公开了一个 getter——可能是因为它的用例。

简而言之:这实际上取决于您将如何使用该变量。在这种特殊情况下,我会说这并不重要。

于 2012-11-12T00:27:22.070 回答
0

我知道这是旧的,但我不会使用这些。您的 HttpRequest 对象是否真的需要保留 Session 对象,或者可以将 Session 对象传递给 HttpRequest 对象的某些需要它的函数?让 HttpRequest 存储此对象是否有充分的理由?

于 2013-12-28T15:27:57.637 回答
0

我喜欢你的第一个选项,(它是使用组合的那个),并且看起来有封装(我不知道是什么使函数集),但我想它正在通过“组件”对象的函数修改某些属性“ session”,该模式也称为“委托”。

另一方面,如果您使用封装,则不能使用“public”,即允许对所有人进行修改。正因为如此,您使用 setter 或 getter,或者在您的代码“set”中

于 2012-11-12T00:43:19.403 回答