访问控制,范围解析操作符,抽象类,对象接口

Posted 一阙梅曲香素笺

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了访问控制,范围解析操作符,抽象类,对象接口相关的知识,希望对你有一定的参考价值。

1.和”public”类似的访问修饰符分别有什么作用?

php中有三种访问修饰符,分别是: 
public(公共的、默认)
protected(受保护的) 
private(私有的) 
用在继承关系的时候
它们可以分别用在类的属性和方法上(类的属性和方法统称为类的成员),用来修饰类成员的访问权限。 
public(公共的、默认) 
PHP5中如果类没有指定成员的访问修饰符,默认就是public的访问权限。 

/* 
以下两个方法声明访问权限效果相同 
*/ 
function say(){}; 
publilc function say(){}; 

当类的成员被声明为public的访问修饰符时,该成员能被外部代码访问和操作。 
private(私有的) 
被定义为private的成员,对于类内部所有成员都可见,没有访问限制。对类外部不允许访问。 
protected(受保护的) 
protected稍微有点复杂,被声明为protected的成员,只允许该类的子类进行访问。 

2、什么是抽象?抽象的关键字以及用法

1、抽象关键字 :abstract

抽象就是无法确切的说明,但又有一定的概念或者名称,在PHP中声明一个抽象类或者方法我们需要使用adstract关键字。

2、抽象方法和抽象类的定义

一个类中至少有一个方法是抽象的,我们称之为抽象类所以如果定义抽象类首先定义抽象方法。

abstract class class1{                                              

   abstract function fun1();

……
}

1、类中至少有一个抽象方法
2、抽象方法不允许有{ }
3、抽象方法前面必须要加abstract


3、抽象类和方法使用规则

抽象类的几个特点:
     1、不能被实例化,只能被继承
     2、继承的派生类当中要把所有抽象方法重载才能实例化

 

实例:

 

 

<?php    
    abstract  class cl1
{
        abstract  function fun1();
        abstract  function fun2();
}
class cl2 extends  cl1
{
    function fun1(){
        echo "第一个";
    }
    function  fun2(){
        echo "第二个";
    }
    
}
$c=new cl2();
echo $c->fun2();?>

子类必须把父类中的抽象方法全部都实现,否则子类中还存在抽象方法,那么子类还是抽象类,还是不能实例化类

 

3、什么是接口?接口的关键字以及用法

 

接口就是抽象的抽象

 

接口interface 是一个规定,给人继承用的东西,有点像抽象类
在里面定义的方法,却不去实例化,而需要别的类去implements 它,而且必须一一实现接口定义的所有方法,

举个例子
interface Shop  
{  
  public function buy($gid);  
  public function sell($gid);  
  public function view($gid);  
}    
我声明一个shop接口类,定义了三个方法:买(buy),卖(sell),看(view),那么继承此类的所有子类都必须实现这3个方法少一个都 不行,如果子类没有实现这些话,就无法运行。实际上接口类说白了,就是一个类的模板,一个类的规定,如果你属于这类,你就必须遵循我的规定,少一个都不 行,但是具体你怎么去做,我不管,那是你的事,如:
 
class BaseShop implements Shop  
{  
  public function buy($gid)  
  {  
  echo(\'你购买了ID为 :\'.$gid.\'的商品\');  
  }  
  public function sell($gid)  
  {  
  echo(\'你卖了ID为 :\'.$gid.\'的商品\');  
  }  
  public function view($gid)  
  {  
  echo(\'你查看了ID为 :\'.$gid.\'的商品\');  
  }  
}

 

 

一、访问控制(可见性)

对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的。

被定义为公有的类成员可以在任何地方被访问。

被定义为受保护的类成员则可以被其自身以及其子类和父类访问

被定义为私有的类成员则只能被其定义所在的类访问。

属性的访问控制

类属性必须定义为公有,受保护,私有之一。如果用 var 定义,则被视为公有。

Note: 为了兼容性考虑,在 PHP 4 中使用 var 关键字对变量进行定义的方法在 PHP 5 中仍然有效(只是作为 public 关键字的一个别名)。在 PHP 5.1.3 之前的版本,该语法会产生一个 E_STRICT 警告。

方法的访问控制

类中的方法可以被定义为公有,私有或受保护。如果没有设置这些关键字,则该方法默认为公有

其它对象的访问控制

同一个类的对象即使不是同一个实例也可以互相访问对方的私有与受保护成员。这是由于在这些对象的内部具体实现的细节都是已知的

 

二、范围解析操作符(::)

范围解析操作符(也可称作 Paamayim Nekudotayim)或者更简单地说是一对冒号,可以用于访问静态成员,类常量,还可以用于覆盖类中的属性和方法。

当在类定义之外引用到这些项目时,要使用类名。

PHP 5.3.0 起,可以通过变量来引用类,该变量的值不能是关键字(如 selfparent  static)。

Paamayim Nekudotayim 选作双冒号操作符的名字似乎有些奇怪。然而,这是 Zend 开发小组在写 Zend Engine 0.5(被用于 PHP 3 中)时所作出的决定。事实上这个词在希伯莱文就是双冒号的意思。 

当一个子类覆盖其父类中的方法时,PHP 不会调用父类中已被覆盖的方法。是否调用父类的方法取决于子类。这种机制也作用于构造函数和析构函数重载以及魔术方法

三、抽象类

可以使用 abstract 来修饰一个类或者方法。

abstract 修饰的类表示这个类是一个抽象类 abstract 修饰的方法表示这个方法是一个抽象方法。

抽象类不能被实例化。

抽象方法是只有方法声明,而没有方法的实现内容

 

可以使用 abstract 来修饰一个类。

abstract 修饰的类表示这个类是一个抽象类。

抽象类不能被实例化。

 

abstract 修饰的类表示这个方法是一个抽象方法。

抽象方法,只有方法的声明部分,没有方法体。

抽象方法没有 {} ,而采用 ;  结束。

一个类中, 只要有一个抽象方法, 这个类必须被声明为抽象类。

抽象方法在子类中必须被重写。

抽象类不一定包含抽象函数的方法,但是包含抽象函数的方法一定是抽象类

 

PHP 5 支持抽象类和抽象方法。定义为抽象的类不能被实例化。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。

继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。例如,子类定义了一个可选参数,而父类抽象方法的声明里没有,则两者的声明并无冲突。 这也适用于 PHP 5.4 起的构造函数。在 PHP 5.4 之前的构造函数声明可以不一样的。

抽象类示例

<?php
abstract class  AbstractClass
{
  // 强制要求子类定义这些方法
     abstract protected function  getValue ();
    abstract protected function  prefixValue ( $prefix );

     // 普通方法(非抽象方法)
     public function  printOut () {
        print  $this -> getValue () .  "\\n" ;
    }
}

class  ConcreteClass1  extends  AbstractClass
{
    protected function  getValue () {
        return  "ConcreteClass1" ;
    }

    public function  prefixValue ( $prefix ) {
        return  " { $prefix } ConcreteClass1" ;
    }
}

class  ConcreteClass2  extends  AbstractClass
{
    public function  getValue () {
        return  "ConcreteClass2" ;
    }

    public function  prefixValue ( $prefix ) {
        return  " { $prefix } ConcreteClass2" ;
    }
}

$class1  = new  ConcreteClass1 ;
$class1 -> printOut ();
echo  $class1 -> prefixValue ( \'FOO_\' ) . "\\n" ;

$class2  = new  ConcreteClass2 ;
$class2 -> printOut ();
echo  $class2 -> prefixValue ( \'FOO_\' ) . "\\n" ;
?> 

//什么样的类是抽象类
/*
 *
 * 被抽象关键字修饰的类就是抽象类
 * 抽象类不一定包含抽象函数的方法,但是包含抽象函数的方法一定是抽象类
 * 抽象类不能直接实例化
 * 可被继承
 * */
abstract class Animal{
    /*
     * 被抽象关键字abstract修饰的方法就是抽象1方法
     * 抽象方法只有声明部分,没有实现部分
     * @return mixed
     *
     * */
abstract public function shout();
}
//继承了抽象类的普通类必须实现抽象类的抽象方法
class Cat extends Animal{
    public function  shout(){

    }
}

四、对象接口

 

接口(interface)抽象方法和静态常量定义的集合。

接口是一种特殊的抽象类,这种抽象类中只包含抽象方法和静态常量

接口中没有其它类型的内容

1、接口的定义

interface 接口名{

public getName();

public setName($name);
}
在接口中的抽象方法只能是 public 的,默认也是 public 权限。
并且不能设置成 private 或者 protected 类型

 

 

使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。

接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。

接口中定义的所有方法都必须是公有,这是接口的特性。

实现(implements

要实现一个接口,使用 implements 操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。

Note:

实现多个接口时,接口中的方法不能有重名。

Note:

接口也可以继承,通过使用 extends 操作符。

Note:

类要实现接口,必须使用和接口中所定义的方法完全一致的方式。否则会导致致命错误。

常量 

接口中也可以定义常量。接口常量和类常量的使用完全相同,但是不能被子类或子接口所覆盖。

范例

*
 * 接口可以认为是特殊的抽象类,但是其实它本身是一个特殊的类别
 * 在接口中只能定义公共的抽象函数方法和静态的常量
 * 接口中的抽象函数方法可以省略public关键字,同时abstract关键字不要书写出来
 * interface IFFly
 * 
 * */
interface IFly
{
    //只能用public
 public  function fly();
 //public abstract function fly();不能写abstract
    
}

接口示例

<?php

// 声明一个\'iTemplate\'接口
interface  iTemplate
{
    public function  setVariable ( $name$var );
    public function  gethtml ( $template );
}


// 实现接口
// 下面的写法是正确的
class  Template  implements  iTemplate
{
    private  $vars  = array();
  
    public function  setVariable ( $name$var )
    {
         $this -> vars [ $name ] =  $var ;
    }
  
    public function  getHtml ( $template )
    {
        foreach( $this -> vars  as  $name  =>  $value ) {
             $template  =  str_replace ( \'{\'  .  $name  .  \'}\' ,  $value$template );
        }
 
        return  $template ;
    }
}

// 下面的写法是错误的,会报错,因为没有实现 getHtml():
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class  BadTemplate  implements  iTemplate
{
    private  $vars  = array();
  
    public function  setVariable ( $name$var )
    {
         $this -> vars [ $name ] =  $var ;
    }
}
?> 

可扩充的接口

<?php
interface  a
{
    public function  foo ();
}

interface  b  extends  a
{
    public function  baz ( Baz $baz );
}

// 正确写法
class  c  implements  b
{
    public function  foo ()
    {
    }

    public function  baz ( Baz $baz )
    {
    }
}

// 错误写法会导致一个致命错误
class  d  implements  b
{
    public function  foo ()
    {
    }

    public function  baz ( Foo $foo )
    {
    }
}
?> 

继承多个接口

<?php
interface  a
{
    public function  foo ();
}

interface  b
{
    public function  bar ();
}

interface  c  extends  a ,  b
{
    public function  baz ();
}

class  d  implements  c
{
    public function  foo ()
    {
    }

    public function  bar ()
    {
    }

    public function  baz ()
    {
    }
}
?>

使用接口常量

<?php
interface  a
{
    const  b  =  \'Interface constant\' ;
}

// 输出接口常量
echo  a :: b ;

// 错误写法,因为常量不能被覆盖。接口常量的概念和类常量是一样的。
class  b  implements  a
{
    const  b  =  \'Class constant\' ;
}
?> 

接口加上类型约束,提供了一种很好的方式来确保某个对象包含有某些方法。参见 instanceof 操作符和类型约束

 

 

 

以上是关于访问控制,范围解析操作符,抽象类,对象接口的主要内容,如果未能解决你的问题,请参考以下文章

Java 封装

Java 封装

Java 封装

Java 封装

Java 封装

Java封装