PHP学习笔记8——类与对象

1. 什么是类

1.1 类的声明与实例化

<?php
/**
 * 类在使用前需要声明,声明一个类使用关键字class
 * Class conn
 */
// 声明一个数据库连接类
class conn
{
    private $dbtype = 'mysql'; // 数据库类型
    private $host = '127.0.0.1'; // 数据库服务器IP
    private $username = 'root'; // 用户名
    private $password = '123456'; // 密码
    private $pre = 'tb_'; // 数据库表前缀
    // 插入数据
    public function insert(){}
    // 更新数据
    public function update(){}
    // 删除数据
    public function delete(){}
    // 查询数据
    public function select(){}
}

// 实例化
$connObj = new conn();
var_dump($connObj);
?>
object(conn)#1 (5) {
  ["dbtype":"conn":private]=>
  string(5) "mysql"
  ["host":"conn":private]=>
  string(9) "127.0.0.1"
  ["username":"conn":private]=>
  string(4) "root"
  ["password":"conn":private]=>
  string(6) "123456"
  ["pre":"conn":private]=>
  string(3) "tb_"
}

1.2 访问类中的成员

<?php

class conn2
{
    public $dbtype = 'mysql';

    private $pre = 'tb_';

    public function test() {
        echo 'test';
    }

    public function test2() {
        echo $this->getPre();
    }

    public function getPre() {
        echo $this->pre;
    }
}
// 实例化conn2
$obj = new conn2();
// 可使用“->”访问类中的成员
$obj->test(); // test
echo "\n";
echo $obj->dbtype, "\n"; // mysql

/**
 * 在对象方法执行的时候会自动定义一个$thiis的特殊变量,表示对象本身的引用。
 * 通过$this->形式可以引用该对象的方法和属性,其作用是完成对象内部成员之间的访问。
 */
$obj->test2(); // tb_
?>

访问对象的成员有时还可以使用“::”符号。使用该符号一般有以下几种情况:

  • parent:: 父类成员,这种形式的访问可调用父类的成员变量常量和方法。
  • self:: 自身成员,这种形式的访问可调用当前类中的静态成员和变量
  • 类名::成员,这种形式的访问可调用类中的变量常量和方法。
<?php

class conn3
{
    public $dbtype = 'mysql';

    // 在类中使用const定义常量HOST
    const HOST = '127.0.0.1';

    public function test() {
        echo "test", "\n";
    }

    public function test1() {
        echo self::HOST; // self访问常量HOST
        self::getDbtype(); // self访问静态方法getDbtype()
    }

    // 使用static修饰的方法称为静态方法
    public static function getDbtype() {
        echo "mysql", "\n";
    }
}

// 类对象实例化
$obj = new conn3();
$obj->test1(); // 127.0.0.1mysql
// 没有实例化类,使用“::”访问类中的方法
conn3::test(); // test
conn3::getDbtype(); // mysql

class conn4 extends conn3
{
    public function testPrint() {
        echo parent::test1();
    }
}
$conn4 = new conn4();
$conn4->testPrint(); // 127.0.0.1mysql
?>

1.3 静态属性和静态方法

在PHP中,通过static关键词修饰的成员属性和方法称为静态属性和静态方法。静态属性和静态方法可在不被实例化的情况下直接使用。

  1. 静态属性

    静态属性属于类本身,而不属于任何实例。静态属性使用static关键词定义,

    • 在类外部使用“类名::静态属性名”的方式访问
    • 在类内部可使用“self::静态属性名”的方式访问。
<?php


class myClass
{
    static $staticVal = 0;
    function getStatic() {
        // self访问静态属性
        echo self::$staticVal;
        self::$staticVal++;
    }
}
echo myClass::$staticVal; // 0
$obj = new myClass();
$obj->getStatic(); // 0
echo myClass::$staticVal; // 1
?>
  1. 静态方法

与静态属性相似,使用static修饰的方法称为静态方法,也可在不被实例化的情况下使用,其属于类而不是被限制到任何一个特定的对象实例。因此, t h i s 使 this在静态方法中不可使用,但可在对象实例中通过“ this->静态方法名”的形式调用静态方法,在类内部需要使用“self::静态方法名”的形式访问。

<?php


class myClass2
{
    static $staticVal = 0;

    public $val = 100;

    static function getStaticVal() {
        echo self::$staticVal;
    }

    static function changeStaticVal() {
        self::$staticVal--;
        echo self::$staticVal;
    }

    function change() {
        // 在类内部使用$this调用静态方法
        $this->changeStaticVal();
    }
}

myClass2::getStaticVal(); // 0

myClass2::changeStaticVal(); // -1

$obj = new myClass2();
$obj->change(); // -2
?>

1.4 构造方法和析构方法

构造方法是在创建对象时自动调用的方法,析构方法是在对象销毁时自动调用的方法。

  1. 构造方法

构造方法常用的场景是在创建对象时用来给变量赋值,构造方法使用“__construct”定义。

<?php


class person
{
    public $name;
    public $age;
    public $gender;
    function __construct($name, $age, $gender)
    {
        $this->name = $name;
        $this->age = $age;
        $this->gender = $gender;
    }

    function get($key) {
        return $this->$key;
    }
}

$test_1 = new person('张三', 18, '男');
echo $test_1->get('name'); // 张三
$test_2 = new person('李四', 16, '女');
echo $test_2->get('gender'); // 女
?>
  1. 析构方法

析构方法是在对象被销毁前自动执行的方法。使用“__destruct”定义。

在PHP中有一种垃圾回收机制,可自动清除不再使用的对象,释放内存。析构方法在垃圾回收程序执行之前被执行。

<?php

class person
{
    public $name;
    public $age;
    public $gender;
    function __construct($name, $age, $gender)
    {
        $this->name = $name;
        $this->age = $age;
        $this->gender = $gender;
    }

    function get($key) {
        return $this->$key;
    }

    function __destruct() {
        echo "execute automatically before destroy", "\n";
}
}

$test_1 = new person('张三', 18, '男');
echo $test_1->get('name'), "\n"; // 张三
$test_2 = new person('李四', 16, '女');
echo $test_2->get('gender'), "\n"; // 女
?>
张三
女
execute automatically before destroy
execute automatically before destroy

2. 封装和继承

2.1 封装

可使用public、protected、private来修饰对象的属性和方法。使用不同修饰符的属性和方法,其可被访问的权限也不同:

  • 使用public修饰的属性和方法可在任何地方调用
  • 如果在类中的属性和方法前面没有修饰符,则默认修饰符为public
  • 使用protected修饰的属性和方法可在本类和子类中被调用,在其他地方调用将会报错
  • 使用private修饰的属性和方法只能在本类中被访问
<?php

class person2
{
    public $name;
    private $age;
    protected $weight;

    function __construct($name, $age, $weight)
    {
        $this->name = $name;
        $this->age = $age;
        $this->weight = $weight;
    }

    private function get($key) {
        return $this->$key;
    }
}

class personB extends person2{
    function key($key) {
        return $this->$key;
    }
}

$obj = new person2('Tom', 22, '60kg');
echo $obj->name; // Tom
// echo $obj->age;
echo $obj->get('age');
$son = new personB('Beta', 18, '55kg');
echo $son->name; // Beta
echo $son->key('weight'); // 55kg
echo $son->key('age');
?>
<?php


class person2
{
    public $name;
    private $age;
    protected $weight;

    function __construct($name, $age, $weight)
    {
        $this->name = $name;
        $this->age = $age;
        $this->weight = $weight;
    }

    public function get($key)
    {
        return $this->$key;
    }
}

class personB extends person2
{
    function key($key)
    {
        return $this->$key;
    }
}

$obj = new person2('Tom', 22, '60kg');
echo $obj->name; // Tom
// echo $obj->age;
echo $obj->get('age'); // 2
echo $obj->get('weight'); // 60kg
$son = new personB('Beta', 18, '55kg');
echo $son->name; // Beta
echo $son->key('weight'); // 55kg
// echo $son->key('age'); // 访问不到age
echo $son->get('age'); // 18
?>

2.2 继承特性

把一个类作为公共基类(父类),其他的类继承自这个基类,则其它类中都具有这个基类的属性和方法,其他类也可以各自额外定义自己不同的属性和方法。

  • 类的继承使用关键词“extends”
  • 在子类中可以使用parent访问父类的方法
  • 在子类中可重写父类的方法
<?php


class student
{
    public $name;
    private $age;
    protected $weight;

    /**
     * student constructor.
     * @param $name
     * @param $age
     * @param $weight
     */
    public function __construct($name, $age, $weight)
    {
        $this->name = $name;
        $this->age = $age;
        $this->weight = $weight;
    }

    function like() {
        echo "I like study.";
    }

    function age() {
        echo "I'm $this->name, $this->age years old this year.";
    }

    protected function get($key) {
        return $this->$key;
    }

    function set($key, $value) {
        $this->$key = $value;
    }
}

class person extends student {

    // 重写父类方法
    function get($key)
    {
        echo $this->$key;
    }

    function what() {
        parent::like(); // 子类中访问父类方法
    }

    function getAge() {
        $this->age(); // 调用继承自父类的方法
    }
}
// 使用继承自父类的__construct方法初始化实例
$obj = new person('张三', 18, '120kg');
$obj->get('name'); // 张三
$obj->get('weight'); // 120kg
$obj->what(); // I like study.
$obj->set('name', '李四');
$obj->getAge(); // I'm 李四, 18 years old this year.
?>

2.3 通过继承实现多态

多态通过继承复用代码而实现,可编写出健壮可扩展的代码,减少流程控制语句(if else)的使用。

<?php

class animal
{
    function skill() {
        echo "This function will be rewrite in the children.";
    }
}

class fish extends animal{
    function skill()
    {
        echo "I can swim!";
    }
}

class dog extends animal{
   function skill()
   {
       echo "I can run!";
   }
}

function test($obj) {
    $obj->skill();
}

test(new fish()); // I can swim!
test(new dog()); // I can run!
?>

猜你喜欢

转载自blog.csdn.net/username666/article/details/106663865