PHP-面向对象笔记

1·对象包含两个部分
2·对象的特点
3·面向对象编程的基本概念
......

4·面向对象的实质
5·面向对象的基本思路
6·面向对象的基本原则
7·类的概念and类的实例化(instantiate)
8·对象案例
9·构造函数
10·析构函数
11·对象引用
12·面向对象--继承
13·面向对象--访问控制
14·面向对象--静态成员
15·面向对象--Final成员
16·数据访问
17·面向对象·接口
18·面向对象--多态
19·面向对象--抽象类
20·面向对象--魔术方法
tostring()
invoke()
call()
callStatic()
get(),set(),isset(),unset()
__clone()**

面向对象->先对象再去面向
1·对象包含两个部分
--对象的组成元素
·是对象的数据模型,用于描述对象的数据
·又被称为对象的属性,或者对象的成员变量。
--对象的行为
·是对象的行为模型,用于描述对象能够做什么事情
·又被称为对象的方法。
2·对象的特点
--每个对象都是独一无二的
--对象是一个特定事物,他的职能是完成特定功能
--对象是可以重复使用的
3·面向对象编程的基本概念
--什么是面向对象?
·面向就是编程的时候一直把对象放在心上
--面向对象编程就是在编程的时候数据结构(数据组织方式)都通过对象的结构进行存储
·属性、方法
--为什么使用面向对象?
·对象的描述方式更贴合真实的世界,有利于大型业务的理解
·在程序设计的过程中用对象的视角分析世界的时候能够拉近程序设计和真实世界的距离
4·面向对象的实质
--面向对象就是把生活中要解决的问题都用对象方式进行存储
·属性 //桌子的颜色
·方法 //詹姆斯投篮,跑,跳
--对象与对象之间通过方法的调用完成互动

5·面向对象的基本思路
--第一步:识别对象
·任何实体都可以被识别为一个对象
--第二步:识别对象的属性
·对象里边存储的数据被识别为属性
·对于不同的业务逻辑,关注的数据不同,对象里面存储的属性也不同
--第三步:识别对象的行为
·对象自己属性数据的改变
·对象和外部交换

6·面向对象的基本原则
--对象内部是高内聚的
·对象只负责一项特定的职能(职能可大可有)
·所有对象相关的内容都封装到对象内部
--对象对外是低耦合的
·外部世界可以看到对象的一些属性(并非全部)
·外部世界可以看到对象可以做某些事情(并非全部)
7·类的概念
--物以类聚,把具有相似特性的对象归类到一个类中
--类定义了这些相似对象拥有的相同的属性和方法
--类是相似对象的描述,称为类的定义,是该类对象的蓝图或者原型
--类的对象称为类的一个实例(Instance)
--类的属性和方法统称为类成员

7·类的实例化(instantiate)
--类的实例化(instantiate)就是通过类定义创建一个类的对象
·比如通过NBA球员的定义创建一个球员对象

8·案例

<?php
// 类的定义以关键字class开始,后面跟着这个类的名称。类的命名通常每个单词的第一个字母大写。
以中括号开始和结束
class Nbaplayer{
//定义属性
public $name="jordan";
public $height="198cm";
public $weight="98kg";
public $team="bull";
public $playerNumber="23";

//构造函数,在对象被实例化时自动调用,一般用于给属性赋值
function __construct($name,$height,$weight,$team,$playerNumber){
//this是php里边的伪变量,表示对象自身。可以通过$this->的方式访问对象的属性和方法
$this->name = $name;
$this->weight = $weight;
$this->team = $team;
$this->playerNumber = $playerNumber;
}
//析构函数,在程序结束的时候会自动调用
//析构函数通常被用于清理程序使用的资源。
function __destruct(){
echo "Destroying".$this-name."\n";
}
//定义方法
public function run(){
echo "Running\n";
}

public function jump(){
echo "Jumping\n";
}

public function shoot(){
echo "Shooting\n";
}

public function dunk(){
echo "Dunking\n";
}

public function pass(){
echo "Passing\n";
}
}

// 类到对象
// 类的实例化为对象时使用关键字new,new之后紧跟类的名称和一对括号
// 每一次用new实例化对象的时候,都会用类名后面的参数列表调用构造函数

$Jordan = new Nbaplayer("jordan","198cm","98kg","bull","23");
//对象的属性成员可以通过->符号来访问
echo $jordan->name."\n";
$jordan->dribble();
$jordan->pass();
// 通过把变量设置为null,可以触发析构函数的调用
// 当对象不会再使用的时候,会触发析构函数
$jordan1 = $jordan;
$jordan2 = &$jordan;
$jordan = null;
echo "gfdgf";
?>

9·构造函数

__construct();
构造函数,在对象被实例化的时候自动调用
function __construct($name,$height){
  // $this是php里面的伪变量,表示对象自身。可以通过$this -> 的方式访问对象的属性和方法
  $this -> name = $name;
  $this -> height -> $height;
}

$jordan = new NbaPlayer('jordan','210cm');
$james = new NbaPlayer('james','203cm');

每一次用new实例化对象的时候,都会用类名后面的参数列表调用构造函数

10·析构函数
__destruct();析构函数
析构函数通常被用于清理程序使用的资源,比如程序使用了打印机,那么可以在析构函数里面释放打印机资源。
1、析构函数,在程序执行结束的时候会自动调用
2、通过把变量设置为NULL,可以出发析构函数的调用
3、析构函数不带任何参数
11·对象引用

12·面向对象--继承
--他们拥有部分相同的属性和方法
--继承的好处
--父类里边定义的类成员可以不用在子类中重复定义,节约了编程的时间和代价
·比如,人的吃这个方法在一旦在父类中调用,那么NBA球员和女主播两个子类就不需要实现吃
这个方法了,就好像天生有这个功能一样
--同一个父类的子类拥有相同的父类定义的类成员,因此外部代码调用它们的时候可以一视同仁
·比如,一个NBA球员和一个女主播,因为它们都是人,所以可以直接调用父类定义的“吃方法”,
而不用管他到底是个NBA球员还是女主播
--子类可以修改和调整父类定义的类成员
·我们称为重写(Overwrite)
·一旦子类修改了,就按照子类修改之后的功能执行

class human{
public $name;
public $height;
public $weight;

public function eat($food){
echo $this->name."s eating".$food."\n";
}

public NbaPlayer extends human{
//继承,但extends后边只能跟一个类名
}
}

13·面向对象--访问控制
--NBA球员一般都不想让其他人知道自己的真实年龄怎么办?
--面向对象的三种访问权限
·public公有的类成员,可以在任何地方被访问
··定义该成员的类(自身)、该类的子类、其他类
·protected受保护的类成员,可以被其自身以及子类访问
·private私有的类成员,只能被自身访问
如果想调用一个类私有的属性,须要在类的里面在封装一个public公开函数,然后通过实例化对象是可以调用类里面的私有属性或者保护属性

14·面向对象--静态成员
--所有NBA成员都有一个共同的联盟总裁“David Sterm”
--总裁换成了“Adam Silver”怎么办?
·换是一个动词,所以应该对应类里边的一个方法
--使用类的静态成员特性就可以达到这样的效果
·static关键字
--在子类中,使用parent关键字parent::$svalue能够访问父类静态成员,在外部
--在静态方法中,不能使用this(因为static静态是全局的不是对象),用static或self关键字

//静态属性定义时在访问控制关键字后面添加static关键字即可
public static $president = "David stern";
//静态方法一样
public static function changePresident($newPrsdt){
//在类定义中使用静态成员时候,有self关键字或static后面跟着::操作符,即可。注意,在访问静态成员的时候,::后面需要跟着$符号
self::$president = $newPrsdt;
}
//在类定义外部访问静态属性,使用类名加::操作符的方法来访问类的静态成员
NbaPlayer::changePresident("Adam Sliver");//只要改这个地方就可以改公有的东西,比如两个NBA球员的总裁
echo NbaPlayer::$president."\n";

15·面向对象--Final成员
--对于吃饭这个功能,不希望子类修改它
--对于NBA球员这个类不希望再创建它的子类
--使用类的Final成员特性就可以达到这样的效果
·final关键字(php 5 才出现)
--添加final关键字能够让这个方法不能在子类中重写
--对于不想被任何类继承的类可以在class之前添加final关键字
--对于不想被子类重写(修改)的方法,可以在方法定义的前面添加final关键字

// 子类中编写跟父类方法名完全一致的方法可以完成对父类方法的重写(overwrite)
//对于不想被任何类继承的类可以在class之前添加final关键字
//对于不想被子类重写(修改)的方法,可以在方法定义的前面添加final关键字

final class BaseClass
{
  public function test(){
  echo "BaseClass::test called\n";
  }
  //添加final关键字能够让这个方法不能在子类中重写
  final public function test1(){
  echo "BaseClass::test1 called\n";
  }
}

class Childclass extends BaseClass{
  public function test($tmp=null){
  echo "ChildClass::test called".$tmp."\n";
  }

}
$obj = new Childclass();
$obj->test("");

16·数据访问 --parent关键字可以用于调用父类中被子类重写了的方法 --self关键字可以用于访问类自身的成员方法,也可以用于访问自身的静态成员和类常量; 不能用于访问自身的属性;使用常量的时候不需要在常量名称前面添加$符号 --static关键字用于访问类自身定义的静态成员,防伪静态属性时需要在属性前面添加$符号

class BaseClass
{
  public function test(){
  echo "BaseClass::test called\n";
  }

  public function test1(){
  echo "BaseClass::test1 called\n";
  }
}

class Childclass extends BaseClass{
  const CONST_VALUE = 'A constant value';
  private static $sValue = 'static value';
  public function test($tmp=null){
  echo "ChildClass::test called".$tmp."\n";
  parent::test();//用parent关键字可以访问被子类重写的方法
  self::called();
  echo self::CONST_VALUE."\n";
  echo static::$sValue."\n";
  }

  public function called(){
  echo "ChildClass::called() called\n";
  }

}
$obj = new Childclass();
$obj->test("");

17·面向对象·接口
--问题
·人会吃饭,动物也会吃饭
·有些植物也可以吃东西(比如说猪笼草)
--吃这个动作(方法)动物和植物的实现方式是不一样的
·吃这个行为没有统一的实现方式
·动物张嘴咀嚼
·植物直接包裹融化

 --接口就是把不同的类的共同行为进行了定义,然后在不同的类里面实现不同的功能
 --一旦某个类实现了某个接口,那么就必须实现接口定义的方法
 --人这个实现了“会吃东西”这个接口,那么人必须实现接口定义的“吃饭”方法
 --某个类实现(implements)了某个接口和继承(extends)了某个类的区别
      ·实现接口跟继承类很相似,但是接口不能直接创建自己的对象
        /如果创建了“会吃东西”这个接口的对象,那么具体怎么吃根本不知道
      ·继承的父类必须有该方法的实现,子类可以重写父类的方法,也可以不重写
      ·接口里面的方法是不需要具体实现的,只要定义了方法的名称和参数可以了,具体的实现必须在实现类中定义
      ·一句话概括:类的方法必须有实现,接口的方法必须为空
      ·//interface关键字用于定义一个接口
      ·//implements关键字用于表示实现某个接口
      ·//实现某个接口之后,必须提供接口中定义的方法的具体实现。
      ·//不能实例化接口 //$eatOBJ = new ICanEat();
      ·//可以用instanceof关键字来判断某个对象是否实现了某个接口
      var_dump($obj instanceof ICanEat);//结果是布尔值
      ·//可以用extends让接口继承接口

<?php

//interface关键字用于定义一个接口
interface ICanEat
{
  //接口里边的方法不需要有方法的实现
  public function eat($food);
}
//implements关键字用于表示实现某个接口
class Human implements ICanEat{
  //实现某个接口之后,必须提供接口中定义的方法的具体实现。
  public function eat($food){
  echo "Human eating ".$food."\n";
  }
}

class Animal implements ICanEat{
  //实现某个接口之后,必须提供接口中定义的方法的具体实现。
  public function eat($food){
  echo "Human eating ".$food."\n";
  }
}

$obj = new Human();
$obj->eat("apple");
$monkey = new Animal();
$monkey->eat("bannana");
//不能实例化接口
//$eatOBJ = new ICanEat();

//可以用instanceof关键字来判断某个对象是否实现了某个接口
var_dump($obj instanceof ICanEat);

function checkEat($obj){
  if($obj instanceof ICanEat){
  $obj->eat('food');
  }else{
  echo "The obj can't eat.\n";
  }
}
checkEat($obj);
checkEat($monkey);

//可以用extends让接口继承接口
interface ICanPee extends ICanEat{
  public function pee();
}
//当类实现子接口时,父接口定义的方法也需要在这个类里面具体实现
class Human1 implements ICanPee{
  public function pee(){

  }
  public function eat($food){

  }
}

//定义一个接口
interface Eat{
  function eat($food)
}

//定义类实现接口
class eats implements Eat{
    function eat($foos){
       echo "吃$food.<br>";
    }
}
//定义一个类
class test{
     private $tmp;
    function __construct(Eat $tmp){
       $this->tmp = $tmp;
    }
    function test1($food){
       $this->tmp->eat($food);
    }
}

//实例化
$human = new eats();
$test = new test($human);
$test->test1('Apple');

18·面向对象--多态
--因为接口的方法实现可以有很多,所以对于接口里边定义的方法的具体实现是多种多样的,这种特性我们称为多态
·比如接口A有两个实现B和C,B和C对A里面定义的方法的实现可以是不同的,这种现象就是多态

// 相同的一行代码,对于传入不同的接口的实现的对象的时候,表现是不同的,这就是多态
function checkEat($obj){
  if($obj instanceof ICanEat){
  $obj->eat('food');
  }else{
  echo "The obj can't eat.\n";
  }
}
checkEat($obj);
checkEat($monkey);

19·面向对象--抽象类 --接口里面的方法都是没有实现的,而类里面的方法都是有实现的。 --有没有一种形态,允许类里面的一部分方法不识现呢? ·当接口中的某些方法对于所有的实现类都是一样的实现方法,只有部分方法需要用到多态的特性 --实例 ·人和动物吃东西是不同的,但是呼吸是相同的,不需要为人和动物分别实现呼吸的功能 --abstract关键字用于定义抽象类 /abstract class ACanEat --在抽象方法前面添加abstract关键字可以表明这个方法是抽象方法不需要具体的实现 /abstract public function eat($food);
--抽象类中可以包含普通的方法,有方法的具体实现 public function breath(){echo "Breath use the air.
";}
--继承抽象类的关键字是extends
--继承抽象类的子类需要实现抽象类中定义的抽象方法

<?php
//abstract关键字用于定义抽象类
abstract class ACanEat
{
  //在抽象方法前面添加abstract关键字可以表明这个方法是抽象方法不需要具体的实现
  abstract public function eat($food);
  //抽象类中可以包含普通的方法,有方法的具体实现
  public function breath(){
  echo "Breath use the air.<br>";
  }
}
//继承抽象类的关键字是extends
class Human extends ACanEat{
  //继承抽象类的子类需要实现抽象类中定义的抽象方法
  public function eat($food){
  echo "Human eating".$food."<br>";
  }
}

class Animal extends ACanEat{
  public function eat($food){
  echo "Animal eating".$food."<br>";
  }
}

$man = new Human();
$man->eat("apple");
$man->breath();//和Animal类公用了抽象类中的breath方法
$monkey = new Animal();
$monkey->eat("banana");
$monkey->breath();

20·面向对象--魔术方法
--tostring():当对象被当做String使用时,这个方法会被自动调用。echo $obj;
--
invoke():当对象被当成方法调用时,这个方法会被自动调用。$obj(4);
<?php

class MagicTest
{
    //__tostring会在把对象转换为string的时候自动调用
    public function __tostring(){
        return "This is the Class MagicTest.<br>";
    }
    //__invoke会在把对象当做一个方法调用的时候自动调用-
    public function __invoke($x){
        echo "__invoke called with$x.<br>";
    }
}
$obj = new MagicTest();
echo $obj;
$obj(5);
 --__call():当对象访问不存在的方法名称时,__call()方法会被自动调用
 --__callStatic():当对象访问不存在的静态方法名称时,__callStatic()方法会被自动调用
 --这两个方法在PHP里面也被称为方法的重载(overloading)
      ·注意区分重写(overwrite)
      ·通过这两个方法,同一个方法的名称的调用可以对应不同的方法实现
      · __call($name,$arguments)
· __callStatic($name,$arguments) //这个方法的参数第一个就是调用的方法的名称,第二个参数是方法调用的参数组成的数组

<?php

class MagicTest
{
    public function __tostring(){
        return "This is the Class MagicTest.<br>";
    }
    public function __invoke($x){
        echo "__invoke called with$x.<br>";
    }
    //方法的重载
    //这个方法的参数第一个就是调用的方法的名称,第二个参数是方法调用的参数组成的数组
    public function __call($name,$arguments){
        echo "Calling".$name."with parameters:".implode(",",$arguments)."<br>";
    }
    //静态方法的重载,注意这个方法需要设定为Static
    public static function __callStatic($name,$arguments){
        echo "Calling".$name."with parameters:".implode(",",$arguments)."<br>";
    }
}
$obj = new MagicTest();
$obj->runTest("para1","para2");
MagicTest::runTest("para1","para2");

 --__get(),__set(),__isset(),__unset()
      ·在给不可访问属性赋值时,__set()会被调用
      ·读取不可访问属性的值时,__get()会被调用
      ·当对不可访问属性调用isset()或empty()时,__isset()会被调用
      ·当对不可访问属性调用unset()时,__unset()会被调用
      ·所谓不可访问属性,实际上就是在调用某个属性时发现这个属性没有被定义,
       这时候不同的操纵会触发不同的魔术方法
      ·这几个方法也被称为属性重载的魔术方法

<?php

class MagicTest
{

    public function __get($name){
        return "Getting the property".$name."<br>";
    }
    public function __set($name,$value){
        return "Setting the property".$name."to".$value."<br>";
    }
    public function __isset($name){
        echo "__isset invoked<br>";
        return true;
    }
    public function __unset($name){
        echo "unsetting property ".$name."<br>";
    }
}
$obj = new MagicTest();
echo $obj->className."\n";
$obj->className = 'MagicClassX';
echo '$obj->className is set?'.isset($obj->className);
echo '$obj->classname is empty?'.empty($obj->empty);
unset($obj->className);

 --__clone()

<?php

class NbaPlayer
{
    public $name;
    function __clone(){
        $this->name = 'TBD';
    }
}
$james = new NbaPlayer();
$james->name = 'James';
echo $james->name."<br>";
$james2 = clone $james;
echo "Before set up:james2's:".$james2->name."<br>";
$james2->name = 'James2';
echo "James's:".$james->name."<br>";
echo "james2's:".$james2->name."<br>";

发表评论