PHP类与对象

22次阅读
没有评论

共计 4406 个字符,预计需要花费 12 分钟才能阅读完成。

最近在准备面试,复习了一下基础,包括 PHP 的类与对象。

1. 类是一种抽象定义,对象是一种实现。

# 定义类
class object
{
}
#实现类(对象)
new object

2. 类中包括属性与方法

访问控制(可见性)
class object
{
  #可在内部调用,可被子类调用,可被外部(对象)调用
  public $a;
  #可在内部调用,可被子类调用
  protected $b;
  #可在内部调用
  private $c;
}

3. 类的自动加载

类的自动加载,之前是使用__autoload(),现在,倾向于使用 spl_autoload_register() 注册器,实现懒加载

‘__’开头的为 php 中的语法糖

spl_autoload_register(function ($class){
    echo $class;exit;
    include $class . '.php';
});
new $a;
#输入
#a

4. 对象继承

继承一个类,就会继承父类的属性与方法(private 可见性除外),如果不覆盖父类的属性和方法,则会全部继承。

class parent_class
{
    public $a;
    public function func_a($arg)
    {echo 'hello' . $arg;}
}
class son extends parent_class
{
}
$model = new son();
$model->func_a('liuser');
#输出
#hello liuser
# 重写子类
class son extends parent_class
{public function func_a($arg)
    {echo '你好' . $arg;}
}
$model = new son();
$model->func_a('liuser');
#输出
#你好 liuser
#调用子类自己的属性
abstract class dbObject
{
    const TABLE_NAME='undefined';
    public static function GetAll()
    {
        # 这里使用 $c 或者 static 都可以
        $c = get_called_class();
        return "SELECT * FROM `".static::TABLE_NAME."`";
    }
}
class dbPerson extends dbObject
{const TABLE_NAME='persons';}
class dbAdmin extends dbPerson
{const TABLE_NAME='admins';}
echo dbPerson::GetAll()."<br>";//output: "SELECT * FROM `persons`"
echo dbAdmin::GetAll()."<br>";//output: "SELECT * FROM `admins`"

5. 抽象类

抽象类用 abstract 表示,当一个类中有一个方法为抽象,则类必须被定义为抽象类,抽象类不能被实例化,只能被继承
抽象类中的方法只是定义其形式,不实现具体方法。

abstract class absclass
{#只能写方法名和参数,不能写具体实现(没有 {} 方法体)abstract protected function say($name);
    abstract public function run();}
class class_1 extends absclass
{
    #这里的可见性级别只能比父类更开发,protected 或者 public,不能使用 private
    protected function say($name)
    {// TODO: Implement say() method.
    }
    public function run()
    {// TODO: Implement run() method.
    }
}

6. 对象接口

接口 (interface), 规则类必须实现的方法,但不需要定义内容,同抽象类相似。
接口中定义的所有方法都必须是公有,这是接口的特性。
接口中的常亮不能被子类覆盖。

抽象中,只有抽象类中的抽象方法必须实现,接口中,只要定义为接口,就必须全部实现。

定义接口:interface
实现接口:implements

interface  template
{public function setVariable($name, $var);
    public function getHtml($template);
}
class template1 implements template
{public function setVariable($name, $var)
    {// TODO: Implement setVariable() method.
    }
    public function getHtml($template)
    {// TODO: Implement getHtml() method.
    }
}

多重继承

interface a
{public function foo();
}
interface b
{public function bar();
}
interface c extends a, b
{public function baz();
}
class d implements c
{public function baz()
    {// TODO: Implement baz() method.
    }
    public function bar()
    {// TODO: Implement bar() method.
    }
    public function foo()
    {// TODO: Implement foo() method.
    }
}

7.trait(特性)

自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait, 说白了就是定义一个 trait, 然后在需要用到的类中使用 use 调用其。
特点:
1. 实现代码复用,解决多重继承问题。
2. 无法被实例化

想象一下,如果你需要在一个类中加上日志的相关方法,会怎么做呢?继承?如果有多个类都需要实现日志的方法呢?
如果需要继承,则违背了继承的原则,除非你的类是和日志相关。可以考虑使用特性解决。

trait log
{
    #记录日志
    public function start()
    {echo time();
    }
    public function end()
    {echo time();
    }
}
class Car
{
    #使用特性 log
    use log;
}
$model = new Car();
$model->start();
$model->end();

使用 use 就是当 trait 中的方法复制到当前的类对象中,可能会产生问题。
比如 log 中定义了 start, 而 car 中也定义了 start,则会产生一个优先级的问题,官方给出的优先级如下:

优先顺序是当前类中的方法会覆盖 trait 方法,而 trait 方法又覆盖了基类中的方法。

9. 重载

动态的创建类方法或属性,使用魔法方法__set __get,注意一下用法。
1. 魔术方法的可见性必须是 public.
2. 如果类方法可类变量存在,则无法使用.


class test
{private $data = [];
    public function __set($name, $value)
    {$this->data[$name] = $value;
    }
    public function __get($name)
    {if($this->data[$name]){return $this->data[$name];
       }
       echo '变量' . $name . '不存在';
    }
}
$model = new test();
$model->name = 'liuser';
echo $model->name;

10. final

定义:如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。
这个很好了解,就不展开了,具体可以点开下面的链接

http://php.net/manual/zh/language.oop5.final.php

11.clone(克隆)

使用 clone 克隆一个对象,会把其进行浅复制。有一些特点
1. 因为是浅复制,所以对象的引用还是会指向对象之前的引用。
2. 如果对象定义了__clone 魔术方法,则在复制完成后会执行__clone
3. 如果类需要定义为单例模式时,则需要防止被克隆, 在__clone 方法写入 exit。

    class c1
{
    public $instance = 0;
    public function __clone()
    {$this->instance  = $this->instance +1 ;}
    public function say()
    {echo 'hello';}
}
$m1 = new c1();
$m2 = clone $m1;
echo $m1->instance;
echo $m2->instance;
输出:0 1 

12. 类型约束

在函数的参数执行参数所属的类型,包括对象、数组、接口

class c1
{public function say(){}}
class c2
{
    #指定必须为 c1 的一个对象
    public function f1(c1 $object)
    {$object->say();
    }
    #指定必须为一个数组
    public function f2(array $list)
    {return $list['k1'];
    }
    #指定必须为一个回调函数
    public function call(callable $call,$data)
    {call_user_func($call,$data);
    }
}

13. 对象与引用

PHP 的引用是别名,就是两个不同的变量名字指向相同的内容。在 PHP 5,一个对象变量已经不再保存整个对象的值。只是保存一个标识符来访问真正的对象内容。当对象作为参数传递,作为结果返回,或者赋值给另外一个变量,另外一个变量跟原来的不是引用的关系,只是他们都保存着同一个标识符的拷贝,这个标识符指向同一个对象的真正内容

class A {public $foo = 1;}
$a = new A;
# $a ,$b 都是同一个标识符的拷贝
$b = $a;
$b->foo = 2;
echo $a->foo."\n";
#结果等于 2 

14. 序列化对象

所有 php 里面的值都可以使用函数 serialize()来返回一个包含字节流的字符串来表示。unserialize()函数能够重新把字符串变回 php 原来的值。序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

注意:如果反序列化,然后调用对象中的方法,则在之前,必须引入该类.
虽然在序列化的时候,不会保存对象的方法,但是在反序列化后,依然可以使用对象中的方法。

class A {
    public $foo = 1;
    public function say()
    {echo 'hello';}
}
$a = new A();
$s_a = serialize($a);
#结果:O:1:"A":1:{s:3:"foo";i:1;}
$b = unserialize($s_a);
var_dump($b);
#object(A)#2 (1) {#["foo"]=>
#  int(1)
#}
$b->say();
#结果 hello
echo $b->foo;
#结果  1
正文完
 0
admin
版权声明:本站原创文章,由 admin 于2018-05-02发表,共计4406字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
验证码