面向对象(OO object)
概念
对象:
在现实世界里我们所面对的事情都是对象,如苹果 猫 电视机等。
而在面向对象的程序设计(OOP)中,
对象是一个由信息及对信息进行处理的描述所组成的描述所组成的整体,
是对现实世界的抽象。
例如:
小猫名字:tom 性别:公,花色:橘色;
小狗名字:Jack性别:公,花色:黑色
面向对象:
面向对象是一种编程思想和方法,它将程序中的数据和操作数据的方法封装在一起,形成”对象“,
并通过对象之间的交互和消息传递来完成程序的功能。
面向对象编程(OOP)强调数据的封装、继承、多态和动态绑定等特性,
使得程序具有更好的可扩展性、可维护性和可重用性。
对象的主要三个特性:
对象的行为:对象可以执行的操作,比如:开灯,关灯就是行为。
对象的形态:对对象不同的行为是如何响应的,比如:颜色,尺寸,外型。
对象的表达:对象的表示就相当于身份证,具体区分在相同的行为与状态下有什么不同 (在面向编程中,对象的表示通常通过类来实现)
面对对象编程的三个主要特征:
封装:指将对象的属性和方法封装在一起,使得外部无法直接访问和修改对象的内部状态。
通过使用访问控制修饰符(public、private、protected)来限制属性和方法的访问权限,从而实现封装。
继承:指可以创建一个新的类,该类继承(extends)了父类的属性和方法,
并且可以添加自己的属性和方法。通过继承,可以避免重复编写相似的代码,并且可以实现代码的重用。
多态:指可以使用一个父类类型的变量来引用不同的子类类型的对象,从而实现对不同对象的统一操作。
多态可以使得代码更灵活,具有更好的可扩展性和可维护性,
在PHP中,多态可以通过实现接口(inteface)和使用抽象类(abstract class)来实行
类(class)
定义了一件事物的抽象特点
类的定义包含了数据的形式以及对数据的操作
类的定义
<?php
class Animal{
public $name = "小猫崽"; //属性
public function eat(){ //方法
echo "在和Jack玩耍";
}
}
?>
类的调用
new实例化对象
<?php
class Animal{
public $name = "小猫崽"; //属性
public function eat(){ //方法或者为函数
echo "在和Jack玩耍";
}
}
$cat = new Animal;
echo $cat->name; 调用类里面的属性name
echo $cat->eat();
?>
方法和属性
类方法(函数)
<?php
class Animal{
public $name = "小猫崽"; //属性
public function eat(){ //方法
echo "在和Jack玩耍";
}
function say(){ //方法(函数) public可以省略
echo "jack and tom 在说话";
}
}
?>
$this
代表自身的对象
<?php
class Animal{
public $name = "小猫崽"; //属性
public function eat(){ //方法
echo $this->name."在和Jack玩耍"; //这里的this代表自身,其实也就是类 class Animal
}
}
$cat = new Animal;
$cat->name = "小花";
echo $cat->eat();
$dog = new Animal;
$dog->name = "大back";
$dog->eat();
?>
访问控制
关键字 public、private、protected
public(公有):公有的类成员可以在 任何地方被访问。
protecte (受保护):受保护的类成员则可以被其自身以及其子类和父类访问(咱家的)
private(私有):私有的类成员则只能被其定义所在的类访问(自己的)
__construct构造函数 编程的执行顺序(在调用类的时候,__construct将会自动调用)
构造函数时 一种特殊的方法,在创建一个新对象时,它会被自动调用。
它可以用来初始化对象的属性或执行其他必要的操作
没有返回值
class testing{ //简化的案例
private $name;
public function __construct($name)
{
$this->name = $name;
}
public function eat(){
echo $this->name."在吃饭";
}
}
$cat = new testing("jery");
$cat->eat();
输出:jery在吃饭
案例:计算动物的出生了多少天数
class Animal {
private $name;
private $birth;
private $age;
public function __construct($name,$birth)
{
$this->name = $name;
$this->birth = $birth;
$days = (time() - strtotime($this->birth))/3600/24;
$this->age = floor($days);
}
public function eat(){
echo $this->name."在吃饭";
}
public function getInfo(){
echo "$this->name 的出生了 $this->age 天,出生日期为:$this->birth";
}
}
$cat = new Animal("tom","2023-05-22");
$cat->getInfo();
$dog = new Animal("jack","2001-09-11");
$dog->getInfo(
__destruct析构函数(一般情况下用不到)
析构函数是一种特殊的方法,它在对象被销毁时自动调用
它可以用来执行一些清理操作,例如释放资源或关闭数据库连接。
当对象不再被引用或脚本执行结束时,析构函数会被自动调用。
<?php
// __destruct() 析构函数
class Testing{
public function say($i){
echo 'saying-'.$i;
}
public function __destruct()
{
echo "析构函数被调用\n";
}
}
// 创建对象
$obj = new Testing();
// 执行其他的操作
for ($i=0; $i <4;$i++){
if($i==3){
unset($obj);
}
if($obj){
$obj->say($i);
}
}
?>
static静态变量和self
[静态]指的是无需对类进行实例化,就可以直接调用这些属性和方法
所有对静态变量进行的操作都会对所有对象起作用
举例:小猫和小狗听到指令来吃饭,指令变化,全部都要听从
<?php
class Testing {
public $name = "tom猫";
public static $cat = "tom";
public function eat(){
echo self::$cat; //self来调用静态方法
//echo Testing::$cat;
}
}
$cat = new Testing;
$cat->name = "汤姆";
$cat->eat();
?>
static静态方法
使用self来调用静态方法
public static function say(){
echo self::$name;
}
在静态方法中可以调用静态方法、静态变量
可以调用非静态方法、非静态变量
public function eat(){
echo $this->name."在吃饭";
}
//使用new self 调用非静态方法
public function say(){
echo (new self)->eat();
}
类的继承(extends)
指可以创建一个新的类,该继承(extends)了父类的属性和方法,
并且可以添加自己的属性和方法。通过继承,可以避免重复编写相似的代码,并且可以实现代码的重用
注意:继承不一定能访问 子类无法访问父类中的私有的内容private
<?php
class Testing {
public $name = "小动物";
protected $age=3;
private $birth='2003';
}
class Cat extends Testing{
// 使用extends cat 来继承Testing 如果cat类中什么都不写,则完全和父类Testing属性相同
public function getAge(){
echo $this->age;
}
}
var_dump(new Testing);
var_dump(new Cat);
$cat = new Cat();
?>
<?php
class Testing {
protected $name;
public function __construct($name)
{
$this->name=$name;
}
public function eat(){
echo $this->name . "在玩耍";
}
}
class Cat extends Testing{
public function meow(){
echo $this->name . "在哭泣";
}
}
$cat = new Cat('tom');
var_dump($cat);
$cat->eat(); //继承自父类的Testing的方法
$cat->meow(); //继承子类的方法
?>
方法和属性的重写
如果从父类继承的方法或属性不能满足子类的需求,可以对其进行改写
也就是在子类中重新编写父类的方法,重复的方法会被子类的方法给顶替
<?php
class Testing {
protected $name;
public function __construct($name)
{
$this->name=$name;
}
public function eat(){
echo $this->name . "在玩耍";
}
}
class Cat extends Testing{
public function eat(){
echo $this->name . "在大鱼大肉";
}
public function meow(){
echo $this->name . "在哭泣";
}
}
$cat = new Cat('tom');
var_dump($cat);
$cat->eat(); //继承自父类的Testing的方法
$cat->meow();
?>
final 关键字
作用:
防止类被继承
防止类的方法被重写
如果在一个类前加final,那么这个类就不能被继承;
final class myClass{
// 类的内容
}
如果在一个方法前加final,那这个方法就不能被重写
final public function eat(){
echo $this->name . "在吃饭";
}
注意: final 不能用于属性
调用父类方法
(在子类的内部调用)
parent::
parent::__construct()
静态延迟绑定 static
是指在运行是根据实际调用的类来确定静态方法或属性的绑定
语法: 'static::$name'
<?php
class Animal{
protected static $name="小动物";
public static function eat(){
echo self::$name . "在吃饭";
echo '----';
echo static::$name . "在吃饭";
}
}
class Cat extends Animal{
protected static $name="小猫";
}
Animal::eat();
Cat::eat();
?>
类的多态 多态和继承有关系
多态性允许不同类的对象对相同的消息作出不同的响应。
多态性通过方法重写(覆盖)和方法重载来实现。
方法重写是指子类重写父类的方法,以改变方法的实现细节。
方法重载是指在同一个类中根据参数个数或类型不同来实现不同功能
需要注意的是,多态性只适合用于继承关系的类,子类必须重写父类的方法才能实现多态性。
<?php
class Animal {
protected $name="动物";
public function makeSound(){
echo "$this->name 在吼叫";
}
}
class Dog extends Animal{
protected $name="小狗";
public function makeSound(){
echo "$this->name 在汪汪汪";
}
}
class Cat extends Animal{
protected $name="小猫";
public function makeSound(){
echo "$this->name 在喵喵喵";
}
}
$animal = new Animal();
$dog = new Dog();
$cat = new Cat();
$animal->makeSound();
$dog->makeSound();
$cat->makeSound();
?>
方法重载
主要是根据类中的参数来实现的
= func_get_args(); 函数是获取参数
$numArgs = func_num_args(); 函数是获取参数的数量
<?php
class Animal {
protected $name="动物";
public function makeSound(){
echo "$this->name 在吼叫";
}
}
class Cat extends Animal {
public function makeSound()
{
$numArges = func_num_args();
switch($numArges){
case 2:
echo '执行参数个数为2的事件';
break;
case 3:
echo '执行参数个数为2的事件';
break;
case 2:
echo '执行参数个数为2的事件';
break;
default:
echo '执行默认事件';
}
}
}
$cat = new Cat;
$cat->makeSound('测试1','测试2');
?>
接口和抽象类
interface(接口)
<?php
interface Testing {
public function a(); 只能放定义,
public function b();
}
?>
接口是指一组方法的集合,不是类,不能被实例化。
可以指定某个类必须实现那些方法,但不需要定义这些方法的具体内容
只可以使用public
通常用于定义一些规范,让代码更加有条理不易出错
例如 小动物必须要吃饭和睡觉,否则就会死!这是必须的,每一个小动物都必须有这两个方法(函数)!
在面向对象编程中,implement 是一个关键字,通常用于类声明中,表示一个类实现了一个接口。当一个类实现了一个接口时,它必须实现接口中定义的所有方法,以满足接口的契约。
<?php
interface Animala {
const Tom = "汤姆";
public function eat();
public function sleep($hours);
public static function jump();
}
class Cat implements Animala { //定义了Cat类并实现了Animala接口
public function eat()
{
echo "tom在吃饭";
}
public function sleep($hours)
{
echo " 要睡$hours 小时";
}
public static function jump()
{
echo "跳跳";
}
}
$cat = new Cat();
$cat->eat();
$cat->sleep(44);
?>
抽象类和抽象方法
和接口非常类似,使用它也是定义一种约束或规范,适合较大型的项目或库使用
抽象类
abstract class Animals{
}
抽象类是一种特殊的类,只能被继承,不能被实例化。
抽象类用于定义一组相关的方法,但这些方法的具体实现有继承它的子类来完成。
子类继承抽象后,必须实现抽象类中的所有抽象方法。
抽象类可以包含方法和抽象方法。
抽象方法
abstract public function xxx();
abstract protected function xxx();
抽象方法是没有具体实现的方法,只有方法的声明,而不需要方法体。
抽象方法只能存在于抽象类中
可以使用protected,但不能使用private私有
abstract class Animals {
abstract public function eat();
abstract public function sleep($hours);
public function play(){
echo '玩耍';
}
}
class Cat extends Animals {
public function eat(){
echo "tom 在吃饭";
}
function sleep($hours){
echo "tom 睡了 $hours 小时";
}
}
$cat = new Cat;
$cat->eat();
$cat->sleep(44);
$cat->play();
抽象类和接口的区别
1、抽象类可以包含非抽象的实现,而接口只能包含方法的声明,没有方法的实现。
2、类只能继承一个抽象类,但可以实现多个接口
3、抽象类可以有构造函数,而接口不能有构造函数
4、抽象类中的方法可以有public、protected、private访问修饰符,而接口中的方法只能是public
5、子类继承抽象类时,必须实现抽象类中所有抽象类中的所有方法。
trait代码复用
解决类的单一继承问题
可同时使用多个trait,用逗号隔开
把常用的、通用的代码抽离出来,写成trait
trait A{
}
trait B{
}
class C{
use A,B;
}
和类的继承非常像,但是trait里面不能有类常量,且trait不能被实例化
更据下面类的继承类修改,对不他们的相同点
class Testing {
protected $name;
public function __construct($name)
{
$this->name=$name;
}
public function eat(){
echo $this->name . "在玩耍";
}
}
class Cat extends Testing{
public function meow(){
echo $this->name . "在哭泣";
}
}
$cat = new Cat('tom');
var_dump($cat);
$cat->eat(); //继承自父类的Testing的方法
$cat->meow(); //继承子类的方法
改变后
trait Testing {
protected $name;
public function __construct($name)
{
$this->name=$name;
}
public function eat(){
echo $this->name . "在玩耍";
}
}
class Cat {
use Testing;
public function meow(){
echo $this->name . "在哭泣";
}
}
$cat = new Cat('tom');
var_dump($cat);
$cat->eat(); //继承自父类的Testing的方法
$cat->meow(); //继承子类的方法
trait中可以使用抽象方法
trait中可以使用静态属性和静态方法
trait中可使用其他trait
trait中可使用parent
同名冲突
当一个类同时引入了多个Trait,并且这些Trait 中存在同名方法时,就会产生方法冲突
use A,B{
//B中的eat函数替换成A 当在代码中使用 "eat" 成员时,应该使用命名空间 B 中的成员,而不是命名空间 A 中的成员
B::eat insteadof A;
//别名定义 将A中eat函数替换成Aeat()
A::eat as Aeat
}
<?php
trait A{
public function eat(){
echo "this is A";
}
}
trait B{
public function eat(){
echo "this is B";
}
}
class T{
use A,B{
B::eat insteadof A;
B::eat as Beat;
}
}
$t = new T();
$t->eat();
?>