面向对象 oop 与类的进阶
- 面向对象 oop
面向过程是从上往下的,跟随的是代码的顺序,面相对象是从下往上的,有了对象往上去找写好的类 - 类与文件的命名
一般我们默认类名与文件名一致,每个类要分配一个文件 - 访问修饰符
访问修饰符除 public 外还有 protected 与 private 两种,且不仅可以用在变量,还可以用在方法- public 共有的,都能访问
- protected 受保护的,只能在本类或子类中访问
- private 私有的,只能在本类中访问
- 构造方法__construct()
class Father{
//可继承
public $name = 'admin';
protected $gender = 'male';
//不可继承
private $age = 18;
public function __construct($n,$g,$a)
{
//在构造函数内都可赋值
$this->name=$n;
$this->gender=$g;
$this->age=$a;
}
public function info(){
//在本类方法内调用
return "father-uname:{$this->name},father-gender:{$this->gender},father-age:{$this->age}";
}
}
class Son extends Father{
//由于父类的$age无法继承过来,我们给子类重新加一个$son_age
private $son_age = 18;
//构造方法重写
public function __construct($n,$g,$a)
{
$this->name=$n;
$this->gender=$g;
$this->son_age=$a;
}
//普通方法重写
public function info(){
//由于父类的$age无法继承过来,我们给子类重新加一个$son_age
return "son-uname:{$this->name},son-gender:{$this->gender},son-age:{$this->son_age}";
}
}
$father = new Father('admin1','male',28);
echo $father->name;
echo '<hr>';
echo $father->info();
echo '<hr>';
echo '<hr>';
$son = new Son('admin','male',18);
echo $son->name;
echo '<hr>';
echo $son->info();
构造方法除了可以给共有变量重新赋值,也可以给受保护的活私有变量重新赋值
- 类的继承 extends
- 子类去继承父类的变量、功能,可以简化代码,父类有的变量跟功能方法就可以省略,但是只有 public 跟 protected 修饰符的两种变量或方法可以继承,private 修饰符的变量或方法无法继承
- 子类继承过来父类的变量跟方法,是可以进行重写的
- 子类继承过来的父类的方法重写时,如果需要用到父类的方法可以使用 parent 关键字来调用
- 如果父类的方法不允许被子类重写,可以在方法前面加上 final 关键字,禁止被子类重写
- 如果一个类不想能被继承,也可以在类的前面加上 final 关键字,禁止被继承
//禁止父类被继承
final class Father{
public $name = 'admin';
//禁止方法被重写
final public function uname(){
echo 'admin222';
}
}
- 类的自动加载 spl_autoload_register()
使用 spl_autoload_register()函数可以实现类的自动加载,在函数内写一个引入 php 文件的匿名函数,当 new 一个类时就会自动去找相关文件。
spl_autoload_register(
function($classname){
require_once $className .'php';
}
);
- 静态成员
- 静态成员使用 static 关键字声明,可以给属性,也可以给方法
- 静态成员的调用不用实例化对象就可以调用
- 静态成员调用的方法是类名+::+属性或方法
- 静态成员由本类调用,为所有实例所共享
- 获取本类静态成员使用的关键词是 self,
self::$username
,类似于普通属性调用中的$this - 普通成员使用后就会销毁,但是静态成员会一直存在于内存中
- 静态成员优点:
- 当存在多个实例时,静态成员在内存中只占一份
- 静态成员执行效率比实例化要高
- 静态成员缺点:
静态成员不能自动销毁,而实例化的普通成员在代码结束后就会销毁
class Father{
public $name;
static $uname = '静态admin';
public $num1 = 1;
static $num2 = 1;
public function add1(){
$this->num1++;
self::$num2++;
return '通过计数查看静态成员为所有实例共享,我是普通成员的数字'.$this->num1.',我是静态成员的数字'.self::$num2;
}
public function add2(){
//静态属性无法销毁,如果想做到与普通属性一样的效果,只能在开头给其重新赋值
self::$num2 = 1;
$this->num1++;
self::$num2++;
return '通过计数查看静态成员为所有实例共享,我是普通成员的数字'.$this->num1.',我是静态成员的数字'.self::$num2;
}
//静态方法由于也是不用实例化就能调用,因此内部没法使用$this调用的普通成员
public static function sta(){
return '我只能调取静态的变量'.self::$uname;
}
}
$fa1 = new Father();
$fa2 = new Father();
$fa3 = new Father();
$fa4 = new Father();
$fa5 = new Father();
$fa6 = new Father();
echo $fa1->add1();
echo '<hr>';
echo $fa2->add1();
echo '<hr>';
echo $fa3->add1();
echo '<hr>';
echo $fa4->add1();
echo '<hr>';
echo $fa5->add1();
echo '<hr>';
echo $fa6->add1();
echo '<hr>';
echo $fa1->add2();
echo '<hr>';
echo $fa2->add2();
echo '<hr>';
echo $fa3->add2();
echo '<hr>';
echo $fa4->add2();
echo '<hr>';
echo $fa5->add2();
echo '<hr>';
echo $fa6->add2();