1

我正在用 PHP 修改我的 OOP 概念。我在这里有一个简单的 php 代码来练习可见性。

当我在 Big_Animal 中将 $name 声明为私有时,

1)为什么当我尝试从类外部为 $name 分配不同的值(即 $lion->name="King")时它不会引发错误?

2)为什么当我尝试在 Lion 类中重新分配 $name 时它不会引发错误(即 $this->name="John")。

据我所知,我很困惑,私有属性只能在定义属性的类中访问。

我不清楚的另一件事是受保护的属性。据我了解,受保护的属性只能在类本身及其子类中访问。它的孙子类可以访问它吗?

谢谢你。

<?php
abstract class Big_Animal{

 private $name="Mary";

  abstract public function Greet();

 public function Describe(){
    return "name: ".$this->name;
}

public function __set($name,$value){
    $this->name=$value;
}

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

class Lion extends Big_Animal{


public function Greet(){
    $this->name="John"; //no error for this
    return " roar!";
}



public function Describe(){
        return parent::Describe()." I'm a Lion!";
    }
}


$lion = new Lion();
$lion->name="King";  //no error for this
echo $lion->Describe();
echo $lion->Greet();

?>
4

4 回答 4

3

因为您正在使用__set()的魔术方法

__set() 在将数据写入不可访问的属性时运行。

也可以通过 获取值,$lion->name因为您也使用__get().

于 2012-08-03T06:41:50.460 回答
3
  1. 您的魔术方法访问器(__set 和 __get)在基类抽象类中是公共的。当您直接访问该属性时,它们会写入私有数据。尝试注释掉魔术方法并查看。然后,输出是“名字:玛丽,我是狮子!吼!”。

  2. 将此添加为 Lion::Describe() 中的第一条语句:

    回声“狮子的名字:”。$this->name 。"\n";

    如您所见,现在的输出是:“Lion's name: King”。$this->name="John"; 和 $lion->name="King"; 正在修改 Lion 类对象的公共属性。不幸的是,您可以同时拥有同名的公共和私有属性,但您可以。它们只是不同的变量(在不同的范围内)。

  3. 孙辈可以访问受保护的财产。您的大多数属性都应该受到保护,除非您有非常充分的理由来保护它(因此使用私有)。公共属性在大型项目中使用不多(取决于您的风格)。我宁愿坚持使用显式访问器。随着项目的进展和变得越来越复杂,您会很高兴选择对每个变量使用访问器。我更喜欢使用生成器来为您生成脚手架访问器。它节省了大量时间,减少了错误,并使访问器的创建更便宜(因此更常见)。

更新(对以下评论的回应):1)和 2)您没有收到错误,因为您正在编辑我在上面 2)中列出的两个实例中的 Public 变量。试试 var_dump($lion):

object(Lion)#1 (2) {
  ["name":"Big_Animal":private]=>
  string(4) "Mary"
  ["name"]=>
  string(4) "John"
}

此外,如果您将私有或受保护的成员变量显式添加到 Lion 类,您将收到预期的错误。我同意你的观点,这不是很直观,但似乎是 PHP 中的当前现实。

3) http://www.ibm.com/developerworks/opensource/library/os-php-7oohabits/有一个为私有成员变量编写公共访问器的示例(尽管我再次建议为受保护成员编写公共访问器变量代替)。

于 2012-08-03T06:55:09.363 回答
1

详细说明我的评论...您正在使用一个名为 __set 的函数,它的作用是每次您尝试为此类的未知属性设置值时,都会调用此特定函数。

在您的函数中,您总是将私有字段名称更改为提供的值。由于此类可以访问其字段,因此已设置。

即使你写了 $lion->foo = "bar",名字也会被设置为 bar,因为你的函数 __set

于 2012-08-03T06:46:24.783 回答
-3

我想你的问题的答案就在这里

抽象方法不能是私有的,因为根据定义,它们必须由派生类实现。如果您不希望它公开,则需要对其进行保护,这意味着它可以被派生类看到,但其他人不能看到。

于 2012-08-03T06:42:13.097 回答