公共,私人和受保护之间有什么区别?

何时以及为什么要在课堂中使用publicprivateprotected函数和变量? 他们有什么区别?

例子:

// Public
public $variable;
public function doSomething() {
  // ...
}

// Private
private $variable;
private function doSomething() {
  // ...
}

// Protected
protected $variable;
protected function doSomething() {
  // ...
}

你用:

  • public范围,使该变量/函数可以在任何地方,对象的其他类和实例中使用。

  • private范围,当你想让你的变量/函数仅在其自己的类中可见时。

  • 当你想让你的变量/函数在扩展包括父类的当前类的所有类中都可见时protected范围。

  • 更多:(全面信息)

  • http://php.net/manual/en/language.oop5.visibility.php

  • dd

    上市:

    当您将方法(函数)或属性(变量)声明为public ,可以通过以下方式访问这些方法和属性:

  • 宣布它的同一个类。
  • 继承上面声明的类的类。
  • 此课程以外的任何外国人也可以访问这些内容。
  • 例:

    <?php
    
    class GrandPa
    {
        public $name='Mark Henry';  // A public variable
    }
    
    class Daddy extends GrandPa // Inherited class
    {
        function displayGrandPaName()
        {
            return $this->name; // The public variable will be available to the inherited class
        }
    
    }
    
    // Inherited class Daddy wants to know Grandpas Name
    $daddy = new Daddy;
    echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
    
    // Public variables can also be accessed outside of the class!
    $outsiderWantstoKnowGrandpasName = new GrandPa;
    echo $outsiderWantstoKnowGrandpasName->name; // Prints 'Mark Henry'
    

    保护:

    当您将方法(函数)或属性(变量)声明为protected ,可以通过访问这些方法和属性

  • 宣布它的同一个类。
  • 继承上面声明的类的类。
  • 局外人成员不能访问这些变量。 “局外人”是指它们不是被声明的类本身的对象实例。

    例:

    <?php
    
    class GrandPa
    {
        protected $name = 'Mark Henry';
    }
    
    class Daddy extends GrandPa
    {
        function displayGrandPaName()
        {
            return $this->name;
        }
    
    }
    
    $daddy = new Daddy;
    echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'
    
    $outsiderWantstoKnowGrandpasName = new GrandPa;
    echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
    

    确切的错误将是这样的:

    PHP致命错误:无法访问受保护的属性GrandPa :: $ name


    私人的:

    当您将方法(函数)或属性(变量)声明为private ,可以通过以下方式访问这些方法和属性:

  • 宣布它的同一个类。
  • 局外人成员不能访问这些变量。 局外人的意义在于,它们不是被声明的类本身的对象实例,甚至是继承声明的类的类。

    例:

    <?php
    
    class GrandPa
    {
        private $name = 'Mark Henry';
    }
    
    class Daddy extends GrandPa
    {
        function displayGrandPaName()
        {
            return $this->name;
        }
    
    }
    
    $daddy = new Daddy;
    echo $daddy->displayGrandPaName(); // Results in a Notice 
    
    $outsiderWantstoKnowGrandpasName = new GrandPa;
    echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error
    

    确切的错误信息将是:

    注意:未定义的属性:Daddy :: $ name
    致命错误:无法访问私有属性GrandPa :: $ name


    使用反射解剖爷爷级

    这个主题并没有超出范围,我在这里添加它只是为了证明反射真的很强大。 正如我在上面的三个例子中所说的, protectedprivate成员(属性和方法)不能在课堂外访问。

    但是,通过反思,您甚至可以通过访问课堂以外的protectedprivate成员来做到超乎寻常的事情!

    那么,反思是什么?

    反思增加了对类,接口,函数,方法和扩展进行反向工程的能力。 另外,它们提供了获取文档注释以获取函数,类和方法的方法。

    前言

    我们有一个名为Grandpas的课程,并说我们有三个属性。 为了容易理解,考虑有三个名字为grandpa的:

  • 马克亨利
  • 约翰克莱什
  • 威尔琼斯
  • 让我们分别将它们(分配修饰符)设置为publicprotectedprivate 。 你很清楚, protectedprivate成员不能在课堂外进行访问。 现在让我们用反思来反驳这个陈述。

    代码

    <?php
    
    class GrandPas   // The Grandfather's class
    {
        public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
        protected  $name2 = 'John Clash';  // This grandpa is mapped to a protected  modifier
        private    $name3 = 'Will Jones';  // This grandpa is mapped to a private modifier
    }
    
    
    # Scenario 1: without reflection
    $granpaWithoutReflection = new GrandPas;
    
    # Normal looping to print all the members of this class
    echo "#Scenario 1: Without reflection<br>";
    echo "Printing members the usual way.. (without reflection)<br>";
    foreach($granpaWithoutReflection as $k=>$v)
    {
        echo "The name of grandpa is $v and he resides in the variable $k<br>";
    }
    
    echo "<br>";
    
    #Scenario 2: Using reflection
    
    $granpa = new ReflectionClass('GrandPas'); // Pass the Grandpas class as the input for the Reflection class
    $granpaNames=$granpa->getDefaultProperties(); // Gets all the properties of the Grandpas class (Even though it is a protected or private)
    
    
    echo "#Scenario 2: With reflection<br>";
    echo "Printing members the 'reflect' way..<br>";
    
    foreach($granpaNames as $k=>$v)
    {
        echo "The name of grandpa is $v and he resides in the variable $k<br>";
    }
    

    输出:

    #Scenario 1: Without reflection
    Printing members the usual way.. (Without reflection)
    The name of grandpa is Mark Henry and he resides in the variable name1
    
    #Scenario 2: With reflection
    Printing members the 'reflect' way..
    The name of grandpa is Mark Henry and he resides in the variable name1
    The name of grandpa is John Clash and he resides in the variable name2
    The name of grandpa is Will Jones and he resides in the variable name3
    

    常见的误解:

    请不要混淆下面的例子。 正如您仍然可以看到的, privateprotected成员不能在不使用反射的情况下在课程之外访问

    <?php
    
    class GrandPas   // The Grandfather's class
    {
        public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
        protected  $name2 = 'John Clash';  // This grandpa is mapped to a protected modifier
        private    $name3 = 'Will Jones';  // This grandpa is mapped to a private modifier
    }
    
    $granpaWithoutReflections = new GrandPas;
    print_r($granpaWithoutReflections);
    

    输出:

    GrandPas Object
    (
        [name1] => Mark Henry
        [name2:protected] => John Clash
        [name3:GrandPas:private] => Will Jones
    )
    

    调试功能

    print_rvar_exportvar_dump是调试器函数。 他们以可读的形式呈现有关变量的信息。 这三个函数将使用PHP 5揭示对象的protected属性和private属性。静态类成员将不会显示。


    更多资源:

  • PHP手册 - OOP属性
  • PHP手册 - OOP可见性
  • Techflirt.com - PHP类中的可见性
  • Jordizle.com - 公开,私人,受PHP 5保护
  • Tuxradar.com - 公共,私人和受保护的


  • 默认情况下,通常认为这是一种很好的做法,因为这可以促进数据封装和良好的界面设计。 在考虑成员变量和方法可见性时,考虑成员在与其他对象的交互中扮演的角色。

    如果你“编码到接口而不是实现”,那么做出可视化决策通常是非常简单的。 一般来说,变量应该是私人的或保护的,除非你有充分的理由暴露它们。 使用公共访问器(getter / setter)来限制和管理对类内部的访问。

    以汽车为例,速度,装备和方向等都是私人实例变量。 你不希望驾驶员直接操纵空气/燃料比例。 相反,您将公开的方法暴露的数量有限。 汽车的接口可能包括accelerate()deccelerate() / brake()setGear()turnLeft()turnRight()等方法。

    司机不知道也不应该关心汽车内部的这些行为是如何实施的,并且暴露该功能可能对司机和其他人造成危险。 因此,设计一个公共接口并将数据封装在该接口后面的好习惯。

    这种方法还允许您在不破坏接口与客户端代码的契约的情况下,改变和改进类中公共方法的实现。 例如,您可以改进accelerate()方法以提高燃油效率,但该方法的使用将保持不变; 客户端代码不需要更改,但仍然可以从效率提升中获益。

    编辑:由于看起来你仍然处于学习面向对象的概念(比任何语言的语法都难以掌握),所以我强烈建议你拿起Matt Zandstra提供的PHP Objects,Patterns和Practice的副本。 这本书首先教会了我如何有效地使用OOP,而不仅仅是教给我语法。 我几年前就已经学会了语法,但是在没有理解OOP的“为什么”的情况下这是没用的。

    链接地址: http://www.djcxy.com/p/3237.html

    上一篇: What is the difference between public, private, and protected?

    下一篇: Sorting an array of JavaScript objects