PHP入门学习笔记之—— PHP 类与对象 (上)

PHP 类与对象

    A、class_基本概念:每个类的定义都以关键字 class 开头,后面跟着类名,可以是任何非 PHP 保留字的名字。
                                  后面跟着一对花括号,里面包含有类成员和方法的定义。
伪变量 $this 可以在当一个方法在对象内部调用时使用。
$this 是一个到调用对象(通常是方法所属于的对象,但也可以是另一个对象,如果该方法是从第二个对象内静态调用的话)的引用。
                  Example #1 面向对象语言中的 $this 变量
<?php
class A
{
    function foo()
    {
        if (isset($this)) {
            echo '$this is defined (';
            echo get_class($this);
            echo ") ";
        } else {
            echo "$this is not defined. ";
        }
    }
}

class B
{
    function bar()
    {
        A::foo();
    }
}

$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>以上例程会输出:
$this is defined (a)
$this is not defined.
$this is defined (b)
$this is not defined.
要创建一个对象的实例,必须创建一个新对象并将其赋给一个变量。
当创建新对象时该对象总是被赋值,除非该对象定义了构造函数并且在出错时抛出了一个异常。

一个类可以在声明中用 extends 关键字继承另一个类的方法和成员。不能扩展多个类,只能继承一个基类。
被继承的方法和成员可以通过用同样的名字重新声明被覆盖,除非父类定义方法时使用了 final 关键字。
可以通过 parent:: 来访问被覆盖的方法或成员。

Example #2 简单的类继承
<?php

    //简单的类定义
    class SimpleClass
    {
        // 成员声明
        public $var = 'a default value';
        public $str = 'this is $this';

        // 方法声明
        public function displayVar() {
            echo $this->var;
            echo "<br />";
            echo $this->str;

        }
    }
    //简单的类继承
    class ExtendClass extends SimpleClass
    {
        // Redefine the parent method
        function displayVar()
        {
            echo "Extending class ";
            echo "<br />";
            parent::displayVar();
        }
    }

    $sc = new SimpleClass();
    var_dump ($sc);
    echo "<br />";

    $extended = new ExtendClass();
    $extended->displayVar();

?>

     B、属性:类的变量成员叫做“属性”,或者叫“字段”、“特征”。
属性声明是由关键字public或者protected或者 private开头,然后跟一个变量来组成。
属性中的变量可以初始化,但是初始化的值必须是常数,这里的常数是指php脚本在编译阶段时就为常数,而不是在编译阶段之后在运行阶段运算出的常数。

在类的成员方法里面,可以通过$this->property(property是属性名字)这种方式来访问类的属性、 方法,
但是要访问类的静态属性或者在静态方法里面却不能使用,而是使用self::$property。

在类的非静态方法里面可以使用伪变量$this,这个伪变量是调用该方法的实例化对象引用
(一般来说该对象是这个方法所在类的实例化对象, 但是也有可能是另外的类的对象,比如在另一个类里面使用静态化来调用这个类的方法 )。

     C、构造函数 :void __construct ([ mixed $args [, $... ]] )
PHP 5 允行开发者在一个类中定义一个方法作为构造函数。
具有构造函数的类会在每次创建对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。
Note: 如果子类中定义了构造函数则不会暗中调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()。

Example #1 使用新标准的构造函数
<?php
class BaseClass {
   function __construct() {
       print "In BaseClass constructor ";
   }
}

class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();
       print "In SubClass constructor ";
   }
}

$obj = new BaseClass();
$obj = new SubClass();
?>


     D、析构函数:void __destruct ( void )
PHP 5 引入了析构函数的概念,这类似于其它面向对象的语言。
析构函数会在到某个对象的所有引用都被删除或者当对象被显式销毁时执行。

Example #2 析构函数示例
<?php
class MyDestructableClass {
   function __construct() {
       print "In constructor ";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "Destroying " . $this->name . " ";
   }
}

$obj = new MyDestructableClass();
?>
     和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。
       Note:
       析构函数在脚本关闭时调用,此时所有的头信息已经发出。
       试图在析构函数中抛出一个异常会导致致命错误。

     E、访问控制 :对属性或方法的访问控制,是通过在前面添加关键字 public、protected 或 private 来实现的。
由 public 所定义的类成员可以在任何地方被访问;
由 protected 所定义的类成员则可以被其所在类的子类和父类访问(当然,该成员所在的类也可以访问);
而由 private 定义的类成员则只能被其所在类访问。
1、对类成员的访问控制
               类成员都必须使用关键字public、protected 或 private 进行定义

Example #1 声明类成员
<?php
/**
 * Define MyClass
 */
class MyClass
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new MyClass();
echo $obj->public; // 这行能被正常执行
echo $obj->protected; // 这行会产生一个致命错误
echo $obj->private; // 这行也会产生一个致命错误
$obj->printHello(); // 输出 Public、Protected 和 Private


/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // 可以对 public 和 protected 进行重定义,但 private 而不能
    protected $protected = 'Protected2';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj2 = new MyClass2();
echo $obj->public; // 这行能被正常执行
echo $obj2->private; // 未定义 private
echo $obj2->protected; // 这行会产生一个致命错误
$obj2->printHello(); // 输出 Public、Protected2,但不会输出 Private

class Bar
{
    public function test() {
        $this->testPrivate();
        $this->testPublic();
    }

    public function testPublic() {
        echo "Bar::testPublic ";
    }
   
    private function testPrivate() {
        echo "Bar::testPrivate ";
    }
}

class Foo extends Bar
{
    public function testPublic() {
        echo "Foo::testPublic ";
    }
   
    private function testPrivate() {
        echo "Foo::testPrivate ";
    }
}

$myFoo = new foo();
$myFoo->test(); // Bar::testPrivate
                // Foo::testPublic
?>
          2、对方法的访问控制
类中的方法都必须使用关键字public、protected 或 private 进行定义。
如果没有设置这些关键字,则该方法会被设置成默认的 public。
              
Example #2 声明类中的方法
<?php
/**
 * Define MyClass
 */
class MyClass
{
    // 构造函数必须是 public
    public function __construct() { }

    // 声明一个 public 的方法
    public function MyPublic() { }

    // 声明一个 protected 的方法
    protected function MyProtected() { }

    // 声明一个 private 的方法
    private function MyPrivate() { }

    // 这个方法也是 public 的
    function Foo()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate();
    }
}

$myclass = new MyClass;
$myclass->MyPublic(); // 这行能被正常执行
$myclass->MyProtected(); // 这行会产生一个致命错误
$myclass->MyPrivate(); // 这行会产生一个致命错误
$myclass->Foo(); // Public、Protected 和 Private 都被调用了


/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // This is public
    function Foo2()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate(); // 这行会产生一个致命错误
    }
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // 这行能被正常执行
$myclass2->Foo2(); // Public 和 Protected 都被调用了,但 Private 不会被调用
?>

     F、对象继承:继承已为大家所熟知的一个程序设计特性,PHP 的对象模型也使用了继承。
            继承将会影响到类与类,对象与对象之间的关系。
            比如,当扩展一个类,子类就会继承父类的所有公有和保护方法。但是子类的方法会覆盖父类的方法。
            继承对于功能的设计和抽象是非常有用的,而且对于类似的对象增加新功能就无须重新再写这些公用的功能。

Example #1 继承代码示例
<?php

class foo
{
    public function printItem($string)
    {
        echo 'Foo: ' . $string . PHP_EOL;
    }
   
    public function printPHP()
    {
        echo 'PHP is great.' . PHP_EOL;
    }
}

class bar extends foo
{
    public function printItem($string)
    {
        echo 'Bar: ' . $string . PHP_EOL;
    }
}

$foo = new foo();
$bar = new bar();
$foo->printItem('baz'); // Output: 'Foo: baz'
$foo->printPHP();       // Output: 'PHP is great'
$bar->printItem('baz'); // Output: 'Bar: baz'
$bar->printPHP();       // Output: 'PHP is great'

?> 

     G、Static关键字 :
    声明类成员或方法为static,就可以不实例化类而直接访问。
    不能通过一个对象来访问其中的静态成员(静态方法除外)。
    属性和方法默认为public。
    由于静态方法不需要通过对象即可调用,所以伪变量$this在静态方法中不可用。
    静态属性不可以由对象通过->操作符来访问。
    用::方式调用一个非静态方法会导致一个E_STRICT级别的错误。
    就像其它所有的PHP静态变量一样,静态属性只能被初始化为一个字符值或一个常量,不能使用表达式。
    所以你可以把静态属性初始化为整型或数组,但不能指向另一个变量或函数返回值,也不能指向一个对象。
    PHP5.3.0之后,我们可以用一个变量来动态调用类。但该变量的值不能为关键字self, parent 或static。

              <?php
class Foo
{
    //静态成员
    public static $my_static = 'foo';
 
    public function staticValue() {
        return self::$my_static;
    }
    //静态方法
    public static function aStaticMethod() {
        echo "This is aStaticMethod";
    }
}
 
class Bar extends Foo
{
    public function fooStatic() {
        return parent::$my_static;
    }
}


print Foo::$my_static . " ";

$foo = new Foo();
print $foo->staticValue() . " ";
print $foo->my_static . " ";      // Undefined "Property" my_static

print $foo::$my_static . " ";
$classname = 'Foo';
print $classname::$my_static . " "; // PHP 5.3.0之后可以动态调用

print Bar::$my_static . " ";
$bar = new Bar();
print $bar->fooStatic() . " ";
echo "<br />";
//static function aStaticMethod()
Foo::aStaticMethod();
$classname = 'Foo';
$classname::aStaticMethod();

?>

         H、抽象类 :
PHP5支持抽象类和抽象方法。抽象类不能直接被实例化,你必须先继承该抽象类,然后再实例化子类。
抽象类中 至少要包含一个抽象方法。如果类方法被声明为抽象的,那么其中就不能包括具体的功能实现。
继承一个抽象类的时候,子类必须实现抽象类中的所有抽象方法;
另外,这些方法的可见性 必须和抽象类中一样(或者更为宽松)。
如果抽象类中某个抽象方法被声明为protected,那么子类中实现的方法就应该声明为protected或者public,而不 能定义为private。

                  
Example #1 抽象类代码示例
<?php
abstract class AbstractClass
{
 // 强制要求子类定义这些方法
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);

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

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_') ." ";

$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') ." ";
?>
以上例程会输出:
ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

     I、接口:使用接口(interface),你可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
我们可以通过interface来定义一个接口,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是public,这是接口的特性。
实现要实现一个接口,可以使用implements操作符。类中必须实现接口中定义的所有方法,否则 会报一个fatal错误。如果要实现多个接口,可以用逗号来分隔多个接口的名称。
Note:
实现多个接口时,接口中的方法不能有重名。

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

常量接口中也可以定义常量。接口常量和类常量的使用完全相同。 它们都是定值,不能被子类或子接口修改。
范例Example #1 接口代码示例
<?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;
    }
}

?>Example #2 Extendable Interfaces
<?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)
    {
    }
}

?>Example #3 多个接口间的继承
<?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()
    {
    }
}
?>Example #4 使用接口常量
<?php
interface a
{
    const b = 'Interface constant';
}

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

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

你可能感兴趣的:(PHP入门学习笔记之—— PHP 类与对象 (上))