之前就再犹豫要不要写这一部分, 因为如果不是要写框架, 这其中的东西, 一般的程序员是不需要理解的.
$o = new stdClass();
$o = new stdClass; // exactly the same
当然, 很多人都认为不应该使用第二种方式, 但我认为, 第二种方式更加优雅.
好的, 私货结束.
关于类的继承问题. 动态的方法很容易理解, 我们可以理解成随着继承链往上走, 直到遇到第一个同名方法.
class A { public function foo(){} }
class B extends A { public function foo(){} }
class C extends A {}
(new B)->foo();
(new C)->foo();
那么, 如果调用 B 的 foo 方法, 调用的是B自身的方法. 如果调用C的 foo 方法, 调用的是A的方法.
接下来要讲的是邪恶的继承. 邪恶的继承是可以破坏封装的.
class A { public function foo() { $this->bar(); } }
class B extends A { public function bar(){ // do some evil } }
(new B)->foo();
foo函数是无辜的, 它不知道自己做了邪恶的事情. 所以大神们会推荐用组合而非继承.
static 方法可以被继承.
class A { public static function foo(){} }
class B extends A { public static function foo(){} }
class C extends A {}
B::foo();
C::foo();
和预想的一样.
接下来就要讲一下不邪恶的继承:
class A {
public static function foo() { self::bar(); }
public static function bar() { // good }
}
class B extends A { public static function bar(){ // do some evil } }
B::foo(); // I am good
但这显然不灵活, 失去了多态.
class A { public static function foo() { static::bar(); } }
你可能会怀疑这个有什么用. 假设你写一个ORM的类库. 你希望用户的表名可以默认不配置.
class UserTask extends OrmBase {} // 默认表名 user_task
class UserHost extends OrmBase {
public static $tableName = 'userhost';
} // 指定表名 userhost
那么假设 getTableName() 方法可以获取表名, 那么这个方法该怎么写呢?
class OrmBase()
{
public static function getTableName()
{
if (static::$tableName) return static::$tableName;
return strtolower(preg_replace('/[A-Z]/', '$0_', get_called_class()));
}
}
当然, 如果你这个是是个效率党人, 那么你一定不能错过cache的机会
public static function getTableName()
{
if (!static::$tableName)
static::$tableName = strtolower(preg_replace('/[A-Z]/', '$0_', get_called_class()));
return static::$tableName;
}
get_called_class()
返回运行时类名.get_class()
返回字面量类名, 等同于 CLASS
$o = new stdClass; $o->foo = ‘bar’; print_r($o);
属性赋值规则
__set()
魔术方法, 使用此.属性获取规则
__get()
isset 规则和此类似
方法调用规则
__call
__callStatic()
专辑: