这在php中是正确的面向对象编程吗?
这可以归类为正确的OOP编程吗这在php中是正确的面向对象编程吗?,php,oop,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')
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;
它不是完全正确的OOP,因为未封装
$greet
变量
为了使它“更正确”(不管这意味着什么),您必须将$greet
参数设置为private,并为其创建一些get和set方法(对于$name
变量也是如此,在使用它之前也应该声明它)
在php中,get方法如下所示:
如果我想获得var:
$hi = new greeting('INSERTNAMEHERE');/*NAME OF PERSON GOES HERE*/
echo $hi->__get('greet') .' '. $hi->__get('name');
get是在greeting类中创建的:
function __get($var){
return $this->$var;
}
设置是相同的:
function __set($var, $val){
$this->$var = $val;
}
嗯,有两件事:
- 洗牌该数组并从外部访问它,让外部调用依赖于被洗牌的数组,感觉不太对。如果有一个方法可以返回数组洗牌的结果,也可以直接返回名称,那就更好了
- 事先声明所有对象属性是一种很好的方式,这样以后就可以对其进行记录。因此,如果您使用
,您应该声明它$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;
}
}
$User = new User(/*..From DB ..*/);
$Greeting = new Greeting($User);
echo $Greeting->getGreeting();
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();
public function getGreeting()
{
return $this->_greetings[0] . ' ' . $this->name;
}
$hi = new Greeting('John');
$hi->shuffleGreetings();
echo $hi->getGreeting(); // for example "Hello John"
echo $hi->getRandomGreeting(); // for example "Hi John"
echo $hi->getGreeting(); // for example "Howdy John" <-- WTF!!
$hi = new RandomGreeting;
echo $hi->greetPerson('John'); // ex "Howdy John"
我可能会为$greet使用getter/setter,而不是将其公开。我不明白为什么它不会被认为是OOP
最好有一个
greet
方法。其思想是用户不需要知道$this->greet是一个数组
因此:
从初学者的角度来看,这是肯定的,但由于这是一个单一的对象,它不能像你可以与多个对象定位 真正的OOP是将应用程序的各个实体分离为对象/依赖项 例如,一个简单的网站将包括以下内容:
- 数据库
- 错误处理
- 会议
- 保安
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,都只会相互交互
这使得代码可以被传输到其他项目,而不必处理很多问题,也就是库
如果对象与closley相关,并且所有对象都捆绑在一起,则可以执行以下操作:
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;
}
}
$User = new User(/*..From DB ..*/);
$Greeting = new Greeting($User);
echo $Greeting->getGreeting();
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();
public function getGreeting()
{
return $this->_greetings[0] . ' ' . $this->name;
}
$hi = new Greeting('John');
$hi->shuffleGreetings();
echo $hi->getGreeting(); // for example "Hello John"
echo $hi->getRandomGreeting(); // for example "Hi John"
echo $hi->getGreeting(); // for example "Howdy John" <-- WTF!!
$hi = new RandomGreeting;
echo $hi->greetPerson('John'); // ex "Howdy John"
事实上,这有点离题。首先,公共变量通常是不好的。您不应该直接从代码访问类的变量。您应该尝试将类提供的功能封装到类本身中 首先,根据您的示例,让我向您展示一种好的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();
OOP背后的一个基本思想是,您拥有对代码中的某些数据结构负责的对象。您上面所写的实际上只是一个数据结构,而不是一个完整的对象,它保存问候语的数据,但并不真正负责处理它并将其提供给其他对象
“更好”的对象将如下所示:
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;
}
}
$User = new User(/*..From DB ..*/);
$Greeting = new Greeting($User);
echo $Greeting->getGreeting();
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();
public function getGreeting()
{
return $this->_greetings[0] . ' ' . $this->name;
}
$hi = new Greeting('John');
$hi->shuffleGreetings();
echo $hi->getGreeting(); // for example "Hello John"
echo $hi->getRandomGreeting(); // for example "Hi John"
echo $hi->getGreeting(); // for example "Howdy John" <-- WTF!!
$hi = new RandomGreeting;
echo $hi->greetPerson('John'); // ex "Howdy John"
现在,您的问候对象完全控制着问候语,您的应用程序代码不必关心对象是如何设置的,它只需要关心它可以用来获取问候语的几个函数。如果您希望最终实现国际化或以某种方式更改问候语,您所需要做的就是更改一个对象
另外,请注意,使用对象并不会使代码面向对象。它需要面向对象,这意味着使用对象来定义应用程序将需要执行的离散任务,而不是让应用程序的每个其他部分都可以完全访问所有数据来执行它将要执行的操作。然后,你只是在构建数据结构。我不得不不同意你得到的其他答案。将greet
设为私有并添加getter
对增加封装几乎没有作用
尽管如此,我认为它的OO设计相当糟糕。一个对象应该代表一些东西(我敢说,一些实际的对象?)在我看来,这里的“对象”实际上是人(或其他什么),其中一个在问候另一个。问候语本身应该是从一个对象传递给另一个对象的消息。我们可以编写一个“问候语”类来保存问候语的文本,但即使我们这样做了,问候语对象本身也应该独立于问候语的来源或目标。为了方便起见,我认为这是可以的。虽然它不是太合适的OOP,也不是特别容易理解的代码。不过,有工作代码总比没有代码好
让我们看一下您的代码:
1 class Greeting {
2
3 public $greet = array('Hi','Hello', 'Howzit', 'Ola', 'Whats up');
4
5 function __construct($name) {
6 $this->name = $name;
7 shuffle($this->greet);
8 }
9 }
第1行:说这个类代表问候语的概念。什么是问候语?我会说“你好约翰”或“你好约翰”或“你好约翰”是一种问候语。事实上,你似乎同意,因为
第3行:…您确实有一个类似问候的列表,只是没有名字。但是这个属性证明了一个问题,为什么你的类被命名为Greeting,而它实际上已经封装了多个Greeting。那么这个班不应该叫“问候语”(注意复数)吗
第3行:将属性命名为“greet”也不是一个好主意。这是一个属性,所以不要给它起动词的名字。动词表示方法
第3行
abstract class GreetingType implements Greeting
{
protected $greeting;
public function getGreeting()
{
return $this->greeting;
}
}
class HiGreeting extends GreetingType
{
protected $greeting = 'Hi';
}
class HelloGreeting extends GreetingType
{
protected $greeting = 'Hello';
}
class HowdyGreeting extends GreetingType
{
protected $greeting = 'Howdy';
}
class NullGreeting extends GreetingType
{
protected $greeting = '';
}
class GreetingFactory
{
public function createGreeting($typeName = NULL)
{
switch(strtolower($typeName)) {
case 'hi': return new HiGreeting;
case 'howdy': return new HowdyGreeting;
case 'hello': return new HelloGreeting;
default: return new NullGreeting;
}
}
}
class Greetings
{
protected $greetings;
protected $nullGreeting;
public function __construct(NullGreeting $nullGreeting)
{
$this->greetings = new ArrayObject;
$this->nullGreeting = $nullGreeting;
}
public function addGreeting(Greeting $greetingToAdd)
{
$this->greetings->append($greetingToAdd);
}
public function getRandomGreeting()
{
if ($this->hasGreetings()) {
return $this->_getRandomGreeting();
} else {
return $this->nullGreeting;
}
}
public function hasGreetings()
{
return count($this->greetings);
}
protected function _getRandomGreeting()
{
return $this->greetings->offsetGet(
rand(0, $this->greetings->count() - 1)
);
}
}
$greeting = $greetings->getRandomGreeting();
if(NULL !== $greeting) {
echo $greeting->getMessage();
}
interface Named
{
public function getName();
}
class Person implements Named
{
protected $name;
protected $greeting;
public function __construct($name, Greeting $greeting)
{
$this->name = $name;
$this->greeting = $greeting;
}
public function getName()
{
return $this->name;
}
public function greet(Named $greetable)
{
return trim(sprintf(
'%s %s',
$this->greeting->getGreeting(),
$greetable->getName()
));
}
}
$greetings->addGreeting($greetingsFactory->createGreeting('Hi'));
$greetings->addGreeting($greetingsFactory->createGreeting('Howdy'));
$greetings->addGreeting($greetingsFactory->createGreeting('Hello'));
$john = new Person('John Doe', $greetings->getRandomGreeting());
$jane = new Person('Jane Doe', $greetings->getRandomGreeting());
echo $john->greet($jane),
PHP_EOL,
$jane->greet($john);