这是在PHP中正确的面向对象编程吗?

时间:2011-03-16 18:02:37

标签: php oop

这可以归类为正确的OOP编程吗?

class Greeting {

    public $greet = array('Hi','Hello', 'Howzit', 'Ola', 'Whats up');

    function __construct($name) {
        $this->name = $name;
        shuffle($this->greet);
    }
}

$hi = new Greeting('INSERTNAMEHERE'); /*NAME OF PERSON GOES HERE*/
echo $hi->greet[1] .' '. $hi->name;

9 个答案:

答案 0 :(得分:79)

答案 1 :(得分:7)

嗯,两件事:

  • 改组那个数组并从外部访问它,并且让外部调用依赖于被洗牌的数组,感觉不对。如果有一个返回数组混洗结果的方法会更好,也可能就是这个名字。

  • 预先声明所有对象属性是一种很好的方式,因此可以在以后记录。因此,如果您使用$this->name,则应声明它。

实施的两个点可能如下所示:

class greeting 
 {
 protected $greet = array('Hi','Hello', 'Howzit', 'Ola', 'Whats up');
 protected $name = null;

 public function __construct($name) 
 {
  $this->name = $name;
 }

 public function greet()
 { 
  shuffle($this->greet);
  return $this->greet[1]." ".$this->name;
 }
}

答案 2 :(得分:6)

从初学者的角度来看,这是肯定的,但由于这是一个单一的对象,因此不能像对待几个对象那样进行定向。

真正的OOP是指将应用程序的各个实体分隔为对象/依赖项。

例如,一个简单的网站将包含以下内容:

  • 数据库
  • 错误处理
  • 会话
  • 安全

这些被称为实体,不应该直接相互影响,这就是为什么有分离。

因此,如果我们想要与Sessions和Security进行交互以使会话安全,我们会向会话对象添加一个方法来返回PHP标准结果,例如数组或字符串,这样很多对象都可以与每个对象进行交互其他没有过多地依赖实际物体。

看看你在问候班的尝试,我会看到类似的东西:

class User
{
    protected $data;

    public function __construct(array $user_data)
    {
        $this->data = $user_data;
    }

    public function getUsername()
    {
        return $this->data['username'];
    }
}

class Greeting
{
    private $message = "welcome to mysite %s";

    public function __construct(string $to_greet)
    {
        $this->message = sprintf($this->message,$to_greet);
    }

    public function getGreeting()
    {
        return $this->message;
    }
}

以下将使用如下:

$User = new User(array(
    'id' => 22,
    'username' => 'Robert Pitt'
));

$Greeting = new Greeting($User->getUsername());

echo $Greeting->getGreeting();

现在我已经提到对象确实直接相互交互,但如果他们这样做,就应该封装它们,以便所有数据库对象,如Database,Result,DB_Error只能相互交互。

这允许代码可以传输到其他项目而不必担心很多问题,也称为库。

如果这些对象是完全相关的,那么捆绑在一起就可以做到这样的事情:

$User = new User(/*..From DB ..*/);
$Greeting = new Greeting($User);

echo $Greeting->getGreeting();

答案 3 :(得分:4)

拥有greet方法可能会更好。这个想法是用户不需要知道$ this-> greet是一个数组。

所以:

class Greeting { 
  protected $greet = array('Hi','Hello', 'Howzit', 'Ola', 'Whats up'); 
  protected $name='You';    

  function __construct($name) {
         $this->name = $name;         
  }

  function greet(){
    shuffle($this->greet);
    echo "{$this->greet[0]} {$this->name}!";
  }

}  
$hi = new Greeting('INSERTNAMEHERE');/*NAME OF PERSON GOES HERE*/ 
$hi->greet(); 

答案 4 :(得分:3)

我不同意[编辑:某些]你得到的其他答案。将greet设为私有并添加getter对于增加封装效果不大。

然而,无论如何,我认为这是非常糟糕的 OO设计。一个对象应该代表一些的东西(我敢说,一些实际的 obect ?)IMO,这里的“对象”真的是人(或其他),其中一个问候对方。问候语本身应该是从其中一个对象传递到另一个对象的消息。我们可能会写一个“问候”类来保存问候语的文本,但即使我们这样做,问候语对象本身也应该独立于问候语的来源或目标。

答案 5 :(得分:2)

实际上,它有点偏离标记。首先,公共变量通常很糟糕。您不应该直接从代码访问类的变量。您应该尝试将类提供的功能封装到类本身中。

首先,让我告诉你一个好的OOP代码如何根据你的例子看起来像:

<?php

class greeting
{
    private static $greets = array('Hi','Hello', 'Howzit', 'Ola', 'Whats up');

    private $name;

    function __construct ($name)
    {
        $this->name = $name;
    }

    function doGreeting ()
    {
        $i = array_rand(self::$greets);
        return self::$greets[$i] . ' ' . $this->name;
    }
}

$hi = new greeting('INSERTNAMEHERE');/*NAME OF PERSON GOES HERE*/
echo $hi->doGreeting();

现在,我们来谈谈这些差异。

首先,问候语存储在静态变量中。由于这些文本可能不会因实例而异,因此将它们存储在由整个类共享的静态变量中会更加高效,因此每个实例都没有自己的数组副本。您还会注意到它是私密的。这是封装。外部代码不需要知道类的内部工作方式,比如变量名。外部代码不需要知道数组,因为它只应该在类本身中使用。

另一个小细节是,名称也在那里声明为私有,因为所有类变量通常都应该是私有的封装。如果需要访问它们,则应通过setter和getter函数完成,如果需要,可以为值提供额外的验证。

代码流也有点不同。我们不是直接从外部代码使用类变量,而是让类本身生成问候语并将其作为字符串返回。这样,外部代码不需要知道如何生成问候语文本或存储名称的位置。它需要知道API,即函数,它们的参数和返回值。他们实际工作的方式应留给班级本身。

此外,由于这显然是针对问候类的功能,因此在将功能编码到类中时,它使代码更具可重用性。 OOP的部分重点是创建可以在需要的地方使用的良好可重用代码。当类功能在类本身时,相同的代码不需要在别处编码。

记住封装和可重用性。这是OOP的两个重点。

答案 6 :(得分:2)

OOP背后的基本思想之一是您拥有对代码中某些数据结构负责的对象。你上面写的只是一个数据结构,而不是一个完整的对象,它保存了问候的数据,但并没有真正负责处理它并为其他对象提供它。

“更好”的对象看起来像这样:

class greeting {
   protected $greet = array('Hi','Hello', 'Howzit', 'Ola', 'Whats up');
   protected $name;
   function __construct($name) {
       $this->name = $name;
   }
   public function greet() {
       return $this->greet[rand(0,5)] . ' ' . $this->name;
   }
}

$hi = new greeting('INSERTNAMEHERE');/*NAME OF PERSON GOES HERE*/
echo $hi->greet();

现在你的greet对象完全控制了问候语,你的应用程序代码不必关心如何设置该对象,它只需要关心它可以用来获得问候语的几个函数。如果您想以某种方式最终国际化或更改问候语,您需要做的就是更改一个对象来执行此操作。

另外,请注意,使用对象不会使您的代码成为OOP。它需要是面向对象,这意味着使用对象来定义应用程序需要执行的离散任务,而不是让应用程序的每个其他部分都可以完全访问它的所有数据来处理它会。然后,您只是构建数据结构。

答案 7 :(得分:1)

它的OOP不完全正确,因为$greet变量未被封装。

要使它“更正确”(无论这意味着什么),你必须将$greet param设为私有并为其创建一些get和set方法(同样适用于$name变量 - - 在使用之前也应该声明。

在php中的一个get方法是这样的:

如果我想获得var:

$hi = new greeting('INSERTNAMEHERE');/*NAME OF PERSON GOES HERE*/
echo $hi->__get('greet') .' '. $hi->__get('name');

在问候类中创建了get:

function __get($var){
    return $this->$var;
}

和set是一样的:

function __set($var, $val){
    $this->$var = $val;
}

答案 8 :(得分:0)

我可能会使用getters / setter来$ greet,而不是公开它。我不明白为什么它不会被认为是OOP。

http://en.wikipedia.org/wiki/Object-oriented_programming