php oops:可见性

时间:2012-08-03 06:35:05

标签: php oop visibility

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

当我在Big_Animal中声明$ name为private时,

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 个答案:

答案 0 :(得分:3)

因为您使用的是__set()

的魔法
  

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

也可以按$lion->name获取值,因为您还使用了__get()

答案 1 :(得分:3)

  1. 您的魔术方法访问器(__set和__get)在基类抽象类中是公共的。当您直接访问该属性时,他们是写入私有数据的人。尝试评论魔术方法,看看。然后,输出是“名字:玛丽我是狮子!吼!”。

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

    回声“狮子的名字:”。 $ this-&gt;名称。 “\ n” 个;

    正如您所看到的,输出现在是:“Lion的名字:King”。两个$ this-&gt; name =“John”;和$ lion-&gt; name =“King”;正在修改Lion类对象的公共属性。不幸的是,你可以拥有同名的公共和私人财产,但你可以。它们只是不同的变量(在不同的范围内)。

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

  4. 更新(对以下评论的回复):  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/有一个为私有成员变量编写公共访问器的例子(尽管如此,我建议再为受保护的成员变量编写公共访问器)。

答案 2 :(得分:1)

详细说明我的评论...你正在使用一个名为__set的函数,这样做的是每当你尝试在这个类的未知属性上设置一个值时,就会调用这个特定的函数。

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

即使您写了$ lion-&gt; foo =“bar”,由于您的函数__set

,名称也会设置为bar

答案 3 :(得分:-3)

我认为您的问题的答案是here

  

抽象方法不能是私有的,因为根据定义它们必须是私有的   由派生类实现。如果你不希望它是公开的,它   需要保护,这意味着它可以通过派生来看待   课程,但没有其他人。