-
Notifications
You must be signed in to change notification settings - Fork 3
Open
Description
面向对象编程
目录
一 属性和 static (静态)关键词
1.1 属性
类的成员变量叫属性(也称为:特性或字段)
1.1.1 属性声明
以访问控制(public, protected, private)开头,紧跟普通变量声明
1.1.2 属性初始化
属性值必须为常数,不能为表达式或需要计算运行的结果
1.1.3 访问方式
- 静态属性(static 修饰的属性),使用范围解析运算符(::)访问
- 非静态属性,使用对象运算符(->)访问
1.2 static (静态)关键词
1.2.1 功能
1.2.2 示例
<?php
class Foo
{
//定义类的静态属性
public static $foo = "foo";
//定义类的静态方法
public static function who()
{
}
}<?php
function add()
{
// 定义静态变量
static $counter = 0;
++$counter;
return $counter;
}1.2.3 使用静态属性或方法
- ① 类的静态属性或方法,可以不实例化直接访问(Foo::bar(), Foo::$bar)
- ② 类实例对象可值通过对象运算符(->)访问静态方法,但不能访问静态属性(✔ $foo->bar(), ✖ $foo->$bar)
- ③ $this (伪变量)在静态方法中不可用
- ④ 静态方法不能访问非静态方法
- ⑤ 静态属性初始化值规则同「1.1.2 属性初始化」
1.3 后期静态绑定(延迟静态绑定)
1.3.1 作用
在调用静态方法时获取实际调用类或对象,而非定义该方法的类(如: Base 父类,和 A 子类,皆定义 get() 方法(或静态方法);实际调用类是 A,则实际对象为 A)
1.3.2 后期静态绑定原理
- 静态方法调用,解析的运行时类为范围解析运算符(::)左侧的类名
- 非静态方法调用,则为调用方法的实例对象
<?php
class Base
{
public function who()
{
var_dump(__CLASS__);
}
public static function t()
{
static::who();
}
public function t1()
{
// @link self:: 的限制 http://php.net/manual/zh/language.oop5.late-static-bindings.php
self::who();
}
public function t2()
{
static::who();
}
}
class A extends Base
{
public function who()
{
var_dump(__CLASS__);
}
}
class B extends Base
{
public function who()
{
var_dump(__CLASS__);
}
}
// 后期静态绑定,调用静态方法
A::t(); // A
B::t(); // B
$a = new A();
$b = new B();
// 后期静态绑定,实例对象调用非静态方法
$a->t2();// A
$b->t2();// B
// 非后期静态绑定
$a->t1();// Base
$b->t1();// Base1.4 类型约束
1.4.1 概念
定义函数或方法是,对参数进行类型限定
1.4.2 支持的类型约束类型
- Array
- Object
- Interface
- callable
1.4.3 不支持的类型约束类型
- int
- string
- float
- bool
- traits
1.5 一个比较完整但无意义的示例
<?php
function dump($data)
{
echo "<pre>";
var_dump($data);
echo "</pre>";
}
class Foo
{
public $commProp = "commProp";
public static $staticProp = "staticProp";
public function commMethodCallStaticMethod()
{
dump("-- start :in commMethodCallStaticMethod--");
dump($this->commProp);
dump("-- start :call staticMethod--");
$this->staticMethod();
}
public function commMethod()
{
dump("-- start: \$this->commProp--");
dump($this->commProp);
}
public static function staticMethodCallCommMethod()
{
dump("-- start --");
$this->commMethod();
}
public static function staticMethod()
{
dump("-- start: self::\$staticProp --");
dump(self::$staticProp);
}
public function delayStaticBindMothod()
{
dump("-- start: static::\$staticProp --");
dump(static::$staticProp);
}
}
class Bar extends Foo
{
public static $staticProp = 'childStaticProp';
}
dump('--dump: Foo::$staticProp');
dump(Foo::$staticProp);
dump('--dump: end');
echo "<br/>";
dump('--dump: Foo::staticMethod()');
Foo::staticMethod();
dump('--dump: end');
echo "<br/>";
dump('--dump: Bar::staticMethod()');
Bar::staticMethod();
dump('--dump: end');
echo "<br/>";
dump('--dump: Foo::delayStaticBindMothod()');
Foo::delayStaticBindMothod();
dump('--dump: end');
echo "<br/>";
dump('--dump: Bar::delayStaticBindMothod()');
Bar::delayStaticBindMothod();
dump('--dump: end');
echo "<br/>";
$foo = new Foo();
dump('--dump: install Foo class $foo->commMethodCallStaticMethod()');
$foo->commMethodCallStaticMethod();
dump('--dump: end');
echo "<br/>";
dump('--dump: install Foo class $foo->staticProp');
dump($foo->staticProp);
dump('--dump: end');
echo "<br/>";
dump('--dump: Foo::staticMethodCallCommMethod()');
Foo::staticMethodCallCommMethod();
dump('--dump: end');
echo "<br/>";二 对象继承与抽象类
::class : 类名解析,使用 ClassName::class 你可以获取一个字符串,包含了类 ClassName 的完全限定名称。这对使用了 命名空间 的类尤其有用。
2.1 对象继承
- 子类将继承父类所有公有(public)和受保护(protected)的方法
- 父类(普通类,抽象类或接口)必须在子类之前定义
2.2 抽象类特性
- 如果类中定义一个及以上抽象方法(abstract public function),则类必须声明为抽象类(abstract class)
- 抽象类不能实例化
- 抽象类只能声明调用方式(及参数),不能定义实现(函数体)
2.3 抽象类继承特性
- 继承类(子类)必须实现抽象类所有抽象方法
- 继承类(子类)实现方法的访问控制(public, protected, private),必须等于或高于抽象类方法
- 继承类(子类)对抽象方法的实现,在参数类型及个数上必须与父类保持一致;
但如果实现方法自定义抽象类中没有的可选参数,则声明不冲突
2.4 示例
<?php
abstract class Weapon
{
abstract public function fireTo();
abstract protected function shoot();
}
class Gun extends Weapon
{
public function fireTo($target = 'enemy')
{
printf("Fire to : %s. %s", $target, PHP_EOL);
}
public function shoot()
{
echo "I'm shoot.";
}
}
$gun = new Gun();
$gun->fireTo();
$gun->shoot();三 对象接口
3.1 定义
- 关键字 interface 定义接口
- 同抽象类一样,仅声明调用方式(及参数),不能定义实现(函数体)
- 接口中所有方法必须公有(public)
- 接口中可定义常量,实现类不能覆写接口中常量
3.2 实现
- 实现类实现接口使用 implements 操作符
- 可实现多个接口
- 实现多个接口时,接口中方法不能有重名方法
- 实现类对接口方法的实现,在参数类型及个数上必须与接口保持一致;
但如果实现方法自定义接口中没有的可选参数,则声明不冲突
3.3 示例
该示例实现了对 2.4 示例的扩展
<?php
/**
* 射击瞄准镜
*/
interface GunSight
{
const MAX_AIM_DISTANCE = 3000;
/**
* [aimAt 瞄准功能]
*/
public function aimAt();
}
/**
* 无限弹药
*/
interface UnlimitedAmmo
{
public function ammo();
}
abstract class Weapon
{
abstract public function fireTo();
abstract protected function shoot();
}
class Gun extends Weapon implements GunSight, UnlimitedAmmo
{
/**
* [fireTo description]
*
* @inherit
*
* @param string $target [description]
*/
public function fireTo($target = 'enemy')
{
printf("Use gun fire to %s. %s", $target, PHP_EOL);
}
/**
* [shoot]
*
* @inherit
*/
public function shoot()
{
printf("now is shooting.%s", PHP_EOL);
}
/**
* [aimAt ]
*
* @implements
*
* @param string $target [description]
*/
public function aimAt($target = 'enemy')
{
printf("Now gun has gun sight,can aim at %s,the max distance is %s m.%s", $target, self::MAX_AIM_DISTANCE, PHP_EOL);
}
/**
* [ammo]
*
* @implements
*/
public function ammo()
{
printf('Unlimited ammo support. %s', PHP_EOL);
}
}
$gun = new Gun();
$gun->ammo();
$gun->aimAt();
$gun->fireTo();
$gun->shoot();三 重载
3.1 PHP 重载的概念
** PHP 重载 **
对象调用类未定义或不可见(private)的类属性或方法时,重载方法会被调用
** 其它语言重载定义 **
TODO
3.2 重载方法
3.2.1 属性重载的魔术方法
- __get($name, $value): 给不可访问属性或未定义属性赋值时被调用
- __set($name): 读取不可访问属性或未定义属性时被调用
- __isset($name): 当不可访问属性或未定义属性调用 isset() 或 empty() 时,被调用
- __unset($name): 当不可访问属性或未定义属性调用 unset() 时,被调用
3.2.2 方法重载的魔术方法
- __call($name, array $arguments): 当对象调用不可访问方法时,被调用
- __callStatic($name, array $arguments): 在静态上下文中调用不可访问方法,被调用
3.3 注意事项
- 重载魔术方法必须声明为 public
- 参数不能为应用传递