本文是我边学PHP边写的学习研究,希望对于需要的人有所帮助。
基本使用:
date_default_timezone_set("PRC");
class NbaPlayer
{
// 类的属性的定义
public $name="Jordan";// 定义属性
public $height="198cm";
public $weight="98kg";
public $team="Bull";
public $playerNumber="23";
// 默认的构造函数,在对象被实例化的时候自动调用
/*function __construct() {
print "In NbaPlayer constructor\n";
}*/
// 构造函数通常用于初始化对象的属性值
function __construct($name, $height, $weight, $team, $playerNumber) {
print $name . ";" . $height . ";" . $weight . ";" . $team . ";" . $playerNumber."\n";
$this->name = $name; // $this是php里面的伪变量,表示对象自身
$this->height = $height; // 通过$this可以设置对象的属性值
$this->weight = $weight;
$this->team = $team;
$this->playerNumber = $playerNumber;
}
// 析构函数,用于清理程序中使用的系统资源,比如释放打开的文件等等
// 析构函数在该对象不会再被使用的情况下自动调用
function __destruct() {
print "Destroying " . $this->name . "\n";
}
// 类的方法的定义
public function run() {
echo "Running\n";
}
public function jump(){
echo "Jumping\n";
}
public function dribble(){
echo "Dribbling\n";
}
public function shoot(){
echo "Shooting\n";
}
public function dunk(){
echo "Dunking\n";
}
public function pass(){
echo "Passing\n";
}
}
/**
* 1. 类实例化为对象时使用new关键字,new之后紧跟类的名称和一对括号。
* 2. 使用对象可以像使用其他值一样进行赋值操作
*/
$jordan = new NbaPlayer("Jordan", "198cm", "98kg", "Bull", "23");
// 访问对象的属性使用的语法是->符号,后面跟着属性的名称
echo $jordan->name."\n";
// 调用对象的某个方法使用的语法是->符号,后面跟着方法的名称和一对括号
$jordan->run();
$jordan->pass();
$james = new NbaPlayer("James", "203cm", "120kg", "Heat", "6");
echo $james->name."\n";
// 当对象变量被赋值为Null的时候,对象的析构函数会被自动调用
// 同一个类的其他对象不受影响
$james = null;
echo "From now on James will not be used anymore.\n";
// 当程序执行结束时,所有类的对象的析构函数都会自动被调用
?>
引用:
// 当对象变量被赋值为Null的时候,对象的析构函数会被自动调用
// 同一个类的其他对象不受影响
$james1 = $james; // 引用赋值操作会产生对象的一个新的引用
$james2 = &$james; // 使用&的引用赋值操作不会产生对象的一个新的引用
$james = null;
继承:
date_default_timezone_set("PRC");
/**
* 继承
* 1. 定义人类
* 2. 让NbaPlayer继承人类
* 3. PHP中类不允许同时继承多个父类,也就是extends后面只能跟一个父类名称,这个特性被称为PHP的单继承特性
*/
class Human{
public $name;
public $height;
public $weight;
public function eat($food){
echo $this->name . "'s eating ". $food. "\n";
}
}
// extends关键字用于说明该类继承自某个父类
class NbaPlayer extends Human
{
// 类的属性的定义
public $team="Bull";
public $playerNumber="23";
private $age="40"; // private 类型的属性不能被对象外部访问,但是可以在对象内部使用
// 默认的构造函数,在对象被实例化的时候自动调用
/*function __construct() {
print "In NbaPlayer constructor\n";
}*/
// 构造函数通常用于初始化对象的属性值
function __construct($name, $height, $weight, $team, $playerNumber) {
print $name . ";" . $height . ";" . $weight . ";" . $team . ";" . $playerNumber."\n";
$this->name = $name; // $this是php里面的伪变量,表示对象自身
$this->height = $height; // 通过$this可以设置对象的属性值
$this->weight = $weight;
$this->team = $team;
$this->playerNumber = $playerNumber;
}
// 析构函数,用于清理程序中使用的系统资源,比如释放打开的文件等等
// 析构函数在该对象不会再被使用的情况下自动调用
function __destruct() {
print "Destroying " . $this->name . "\n";
}
// 类的方法的定义
public function run() {
echo "Running\n";
}
public function jump(){
echo "Jumping\n";
}
public function dribble(){
echo "Dribbling\n";
}
public function shoot(){
echo "Shooting\n";
}
public function dunk(){
echo "Dunking\n";
}
public function pass(){
echo "Passing\n";
}
}
/**
* 1. 类实例化为对象时使用new关键字,new之后紧跟类的名称和一对括号。
* 2. 使用对象可以像使用其他值一样进行赋值操作
*/
$jordan = new NbaPlayer("Jordan", "198cm", "98kg", "Bull", "23");
// 访问对象的属性使用的语法是->符号,后面跟着属性的名称
echo $jordan->name."\n";
// 调用对象的某个方法使用的语法是->符号,后面跟着方法的名称和一对括号
$jordan->run();
$jordan->pass();
$jordan->eat("apple"); // 只要是Human类的子类的对象,就可以调用eat方法
?>
private $age="40"; // private 类型的属性不能被对象外部访问,但是可以在对象内部使用
public function getAge(){
echo $this->name . "'s age is " . ($this->age - 2) . "\n";
}
protected $height; // 只有自身和子类可以访问到
static关键字:
public static $president="David Stern";
public static function changePresident($newPrsdt){
static::$president = $newPrsdt; // self用于表示当前类,"::"操作符用于访问类的静态成员
// static关键字也可以用于访问当前类的静态成员
// echo $this->age . "\n"; // 不能在静态方法中使用this伪变量,也不能用对象的->方式调用静态成员
echo parent::$sValue . "\n"; // parent用于表示父类,可以用于访问父类的静态成员
}
// 类名加“::”可以访问类的静态成员
// 静态成员不需要实例化就可以访问
echo "The president is ". NbaPlayer::$president. "\n";
NbaPlayer::changePresident("Adam Silver");
echo "The president is changed to ". NbaPlayer::$president. "\n";
final关键字:
date_default_timezone_set("PRC");
/**
* 重写和Final
* 1. 子类中编写跟父类完全一致的方法可以完成对父类方法的重写
* 2. 对于不想被任何类继承的类可以在class之前添加final关键字
* 3. 对于不想被子类重写(overwrite, 修改)的方法,可以在方法定义前面添加final关键字
*/
class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
public function moreTesting() {
echo "BaseClass::moreTesting() called\n";
}
}
class ChildClass extends BaseClass {
// 重写时参数不一定要跟父类完全一致
public function moreTesting($tmp=null) {
echo "ChildClass::moreTesting() called\n";
}
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
$obj = new ChildClass();
$obj->moreTesting();
?>
数据访问:
date_default_timezone_set("PRC");
/**
* 数据访问补充
* 1. parent关键字可以用于调用父类被重写的类成员
* 2. self关键字可以用于访问类自身的成员方法,也可以用于访问自身的静态成员和类常量;不能用于访问类自身的属性;访问类常量时不用在常量名称前面加$符号
* 3. static关键字用于访问类自身定义的静态成员,访问静态属性时需要在属性名前面添加$符号
*/
class BaseClass {
public function test() {
echo "BaseClass::test() called\n";
}
public function moreTesting() {
echo "BaseClass::moreTesting() called\n";
}
}
class ChildClass extends BaseClass {
public $height="198cm";
private static $sValue = "static value";
const CONST_VALUE = 'A constant value';
public function moreTesting() {
echo "ChildClass::moreTesting() called\n";
parent::moreTesting(); // parent关键字可以访问父类被重写的成员
// step 3 self关键字可以访问该类自身的其他成员
self::called();
// step 4 self关键字可以访问该类定义的常量
echo "CONST_VALUE: " . self::CONST_VALUE."\n";
// 常量不能被赋值修改
// self::CONST_VALUE = 11;
// step 5 static关键字可以访问静态成员,当调用静态属性时记得加$符号
echo "sValue: " . static::$sValue."\n";
}
// step 3
public function called(){
echo "ChildClass::called() called\n";
}
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
$obj = new ChildClass();
$obj->moreTesting();
?>
接口:
date_default_timezone_set("PRC");
/**
* 接口
* 1. 接口的基本概念和基本使用方法
* 2. 接口里面的方法没有具体的实现
* 3. 实现了某个接口的类必须提供接口中定义的方法
* 4. 不能用接口创建对象,但是能够判断某个对象是否实现了某个接口
* 5. 接口可以继承接口(interface extends interface)
* 6. 接口中定义的所有方法都必须是公有,这是接口的特性。
*/
interface ICanEat {
public function eat($food);
}
// Human类实现了ICanEat接口
class Human implements ICanEat {
// 跟Animal类的实现是不同的
public function eat($food){
echo "Human eating " . $food . "\n";
}
}
// Animal类实现了ICanEat接口
class Animal implements ICanEat {
public function eat($food){
echo "Animal eating " . $food . "\n";
}
}
// step1 不同的类可以实现同一个接口,定义接口方法的不同实现
$man = new Human();
$man->eat("Apple");
$monkey = new Animal();
$monkey->eat("Banana");
// step2 尝试删除Human的eat方法并运行
// 实现了某个接口的类必须提供接口中定义的方法
// step3 不能用接口创建对象,但是能够判断某个对象是否实现了某个接口
//$eatObj = new ICanEat();
var_dump($man instanceof ICanEat); // 判断某个对象是否实现了某个接口
// step 4 接口可以继承接口
interface ICanPee extends ICanEat {
public function pee();
}
class Human1 implements ICanPee{
public function pee(){}
}
?>
多态:
date_default_timezone_set("PRC");
/**
* 多态
* 1. 只要某个对象实现了接口(instanceof),就可以直接在对象上调用接口的方法
*/
interface ICanEat {
public function eat($food);
}
// Human类实现了ICanEat接口
class Human implements ICanEat {
// 跟Animal类的实现是不同的
public function eat($food){
echo "Human eating " . $food . "\n";
}
}
// Animal类实现了ICanEat接口
class Animal implements ICanEat {
public function eat($food){
echo "Animal eating " . $food . "\n";
}
}
function eat($obj){
if($obj instanceof ICanEat){
$obj->eat("FOOD"); // 不需要知道到底是Human还是Animal,直接吃就行了
}else{
echo "Can't eat!\n";
}
}
$man = new Human();
$monkey = new Animal();
// 同样的代码,传入接口的不同实现类的时候,表现不同。这就是为什么成为多态的原因。
eat($man);
eat($monkey);
?>
抽象类:
date_default_timezone_set("PRC");
/**
* 抽象类
* 1. 抽象类允许类里面的部分方法暂时没有具体实现,这些方法我们成为抽象方法
* 2. 一旦类里面有抽象方法,这个类就必须是抽象类
* 3. 抽象类跟接口一样,不能直接实例化为对象
*/
// 抽象类前面以abstract关键字开始
abstract class ACanEat {
// 没有实现的方法需要设定为抽象方法
// 抽象方法需要在子类中实现
abstract public function eat($food);
public function breath(){
echo "Breath use the air.\n";
}
}
// Human类实现了ICanEat接口
class Human extends ACanEat {
// 跟Animal类的实现是不同的
public function eat($food){
echo "Human eating " . $food . "\n";
}
}
// Animal类实现了ICanEat接口
class Animal extends ACanEat {
public function eat($food){
echo "Animal eating " . $food . "\n";
}
}
$man = new Human();
$man->eat("Apple");
$man->breath(); // 和Animal共用了抽象类ICanEat的breath方法
$monkey = new Animal();
$monkey->eat("Banana");
$monkey->breath();
?>
魔术方法:
date_default_timezone_set("PRC");
/**
* 魔术方法1
* 1. 当对象被当做String使用时,__tostring()会被自动调用
* 2. 当对象被当成方法调用时,__invoke()会被自动调用
*/
class MagicTest{
public function __tostring(){
return "This is the Class MagicTest.\n";
}
public function __invoke($x){
echo "__invoke called with parameter " . $x . "\n";
}
}
$obj = new MagicTest();
echo $obj;
$obj(5);
?>
date_default_timezone_set("PRC");
/**
* 魔术方法2之方法重载
* 1. 当对象访问不存在的方法名称时,__call()方法会被自动调用
* 2. 当对象访问不存在的静态方法名称时,__callStatic()方法会被自动调用
*/
class MagicTest{
public function __tostring(){
return "This is the Class MagicTest.\n";
}
public function __invoke($x){
echo "__invoke called with parameter " . $x . "\n";
}
public function __call($name, $arguments){
echo "Calling " . $name . " with parameters: " . implode(', ', $arguments) . "\n";
}
public static function __callStatic($name, $arguments){
echo "Static calling " . $name . " with parameters: " . implode(', ', $arguments) . "\n";
}
}
$obj = new MagicTest();
$obj->runTest("para1", "para2");
MagicTest::runTest("para3","para4");
?>
date_default_timezone_set("PRC");
/**
* 魔术方法3之属性重载
* 1. 在给不可访问属性赋值时,__set() 会被调用。
* 2. 读取不可访问属性的值时,__get() 会被调用。
* 3. 当对不可访问属性调用 isset() 和empty()时,__isset() 会被调用。
* 4. 当对不可访问属性调用 unset() 时,__unset() 会被调用
*/
class MagicTest{
public function __tostring(){
return "This is the Class MagicTest.\n";
}
public function __invoke($x){
echo "__invoke called with parameter " . $x . "\n";
}
public function __call($name, $arguments){
echo "Calling " . $name . " with parameters: " . implode(', ', $arguments) . "\n";
}
public static function __callStatic($name, $arguments){
echo "Static calling " . $name . " with parameters: " . implode(', ', $arguments) . "\n";
}
// 通过这两个方法可以实现动态的对象属性
public function __get($name){
return "Getting the property " . $name;
}
public function __set($name, $value){
echo "Setting the property " . $name . " to value ". $value. "\n";
}
public function __isset($name){
echo "__isset invoked\n";
return false;
}
public function __unset($name){
echo "unsetting property " . $name;
}
}
$obj = new MagicTest();
echo $obj->name . "\n";
$obj->name = "Name Value";
echo '$obj->name is set? '. isset($obj->name) . "\n";
echo '$obj->name is empty?' . empty($obj->name) . "\n";
unset($obj->name);
?>
class nbaPlayer{
public $name;
function __clone(){
$this->name='TBD';
}
}
$james=new nbaPlayer();
$james2=clone $james;//没有__clone,james2是新的实例,但属性值相同;有了__clone,james2的$name值是'TBD'