面向对象编程:深入理解OO思想及其核心特性

PHP 面向对象

面向对象编程:深入理解OO思想及其核心特性

面向对象是一种编程思想和方法。它把程序中的数据与操作数据的方法封装起来,形成“对象”。通过对象之间的交互和消息传递来达成程序的功能。面向对象编程注重数据的封装、继承、多态以及动态绑定等特性,这使程序具备更好的可扩展性、可维护性和可重用性。

在面向对象的程序设计里,对象是一个整体。它由信息以及对这些信息进行处理的描述所构成。同时,对象是对现实世界的一种抽象。

在现实世界中,我们所面对的事物都是对象。例如有计算机,有电视机,还有自行车等。

对象的主要三个特性:

动物是一个抽象类,我们能够具体到某一只狗和某一只羊,狗和羊属于具体的对象,它们具有颜色属性,能够书写,能够奔跑等行为状态。

面向对象编程的三个主要特性:

面向对象内容

在下图里,我们利用 Car 类构建出了三个对象,分别是 Mercedes、Bmw 和 Audi。

$mercedes = new Car ();
$bmw = new Car ();
$audi = new Car ();

PHP 类定义

PHP 定义类通常语法格式如下:


解析如下:

实例

url = $par;
  }
  
  function getUrl(){
     echo $this->url . PHP_EOL;
  }
  
  function setTitle($par){
     $this->title = $par;
  }
  
  function getTitle(){
     echo $this->title . PHP_EOL;
  }
}
?>

变量 $this 代表自身的对象。

PHP_EOL 为换行符。

PHP 中创建对象

类创建后,我们可以使用 new 运算符来实例化该类的对象:

$runoob = new Site;
$taobao = new Site;
$google = new Site;

我们创建了以上这些代码中的三个对象,这三个对象各自都是相互独立的。接下来,我们要来看一看怎样去访问成员方法以及成员变量。

调用成员方法

实例化对象之后,我们能够利用这个对象去调用成员方法,而这个对象的成员方法仅仅能够对该对象的成员变量进行操作。

// 调用成员函数,设置标题和URL
$runoob->setTitle( "菜鸟教程" );
$taobao->setTitle( "淘宝" );
Google 设置了标题为“Google 搜索”。
$runoob 把网址设置为 'www.runoob.com' 。
$taobao 设置了网址为“www.taobao.com”。
Google 设置了网址为“www.google.com”。
// 调用成员函数,获取标题和URL
$runoob->getTitle();
$taobao->getTitle();
$google->getTitle();
$runoob->getUrl();
$taobao->getUrl();
$google->getUrl();

完整代码如下:

实例

运行实例 »

执行以上代码,输出结果为:

菜鸟教程
淘宝
Google 搜索
www.runoob.com
www.taobao.com
www.google.com

PHP 构造函数

构造函数是一种特殊的方法。它主要的作用是在创建对象的时候去初始化对象,也就是给对象的成员变量赋予初始值。并且它在创建对象的语句中是与 new 运算符一起被使用的。

PHP 5 能够让开发者在一个类里面定义一个方法当作构造函数,其语法格式是这样的:

构造函数,接受一个或多个参数(可以是混合类型),参数名可以是 $args 等,具体参数个数和类型根据实际情况而定。

在上述例子里,我们能够借助构造方法去对 $url 以及 $title 这两个变量进行初始化。

这个函数名为 __construct,它接收两个参数,分别是 $par1 和 $par2 。
   $this->url = $par1;
   $this->title = $par2;
}

现在我们无需再调用 setTitle 这个方法了,同时也无需再调用 setUrl 这个方法了。

实例

$runoob 被创建为一个新的站点,其地址为“www.runoob.com”,它被称为“菜鸟教程”。

$taobao 被创建为一个新的站点,其网址为“www.taobao.com”,它被命名为“淘宝”。

创建了一个名为 $google 的新站点,其地址为 'www.google.com',用途是进行 'Google 搜索'。

//调用成员函数,获取标题和URL

$runoob->getTitle();

$taobao->getTitle();

$google->getTitle();

$runoob->getUrl();

$taobao->getUrl();

$google->getUrl();

运行实例 »

析构函数

析构函数与构造函数的作用相反。当对象的生命周期结束的时候,比如对象所在的函数已经调用完毕,系统就会自动去执行析构函数。

PHP 5 引入了析构函数这一概念,此概念类似于其他面向对象的语言。其语法格式具体如下:

void __destruct ( void )

实例

name = "MyDestructableClass";
   }
   function __destruct() {
打印“销毁”。然后输出这个对象的名称。换行。
   }
}
创建了一个名为$obj的对象,该对象是 MyDestructableClass 的实例。
?>

执行以上代码,输出结果为:

构造函数
销毁 MyDestructableClass

继承

PHP 通过使用关键字 extends 来实现对一个类的继承。并且 PHP 不具备多继承的支持能力,其继承的格式如下:

class Child extends Parent {
   // 代码部分
}

实例

Child_Site 类把 Site 类继承了下来,并且对功能进行了扩展。

category = $par;
    }
  
    function getCate(){
输出这个类的类别。
    }
}

方法重写

如果父类继承的方法无法满足子类的需求,那么可以对其进行改写。这个对父类继承方法进行改写的过程叫做方法的覆盖,也可以称为方法的重写。

实例中重写了 getUrl 与 getTitle 方法:

function getUrl() {
   echo $this->url . PHP_EOL;
   return $this->url;
}
   
function getTitle(){
   echo $this->title . PHP_EOL;
   return $this->title;
}

访问控制

PHP 实现对属性或方法的访问控制,是通过在其前面添加特定的关键字。其中有 public(公有),用于实现公有访问控制;还有 protected(受保护),用于实现受保护的访问控制;以及 private(私有),用于实现私有的访问控制。

属性的访问控制

类属性需定义为公有、受保护或私有其中之一。若通过 var 来定义,那么它会被当作公有。

public;
        echo $this->protected;
        echo $this->private;
    }
}
$obj = new MyClass();
这行代码可以正常执行,它输出了 $obj 对象的 public 属性。
这行代码会导致一个致命错误,即输出 $obj->protected 的值。
echo $obj->private; 这会导致一个致命错误。
调用 $obj 的 printHello() 方法,该方法用于输出 Public、Protected 和 Private。
/**
 * Define MyClass2
 */
MyClass2 是 MyClass 的子类。MyClass2 继承自 MyClass。MyClass2 从 MyClass 派生而来。
{
可以对 public 和 protected 进行重新定义,然而 private 是不可以的。
这个变量被保护着,它的值为 'Protected2'。
    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}
$obj2 = new MyClass2();
这行代码能够被正常执行,它是关于 $obj2 的 public 属性的操作。
输出 $obj2 所指向对象的 private 属性;然而该属性未被定义。
echo 该对象的 protected 属性; // 此行将会引发一个致命错误
输出 Public、Protected2 和 Undefined。这是通过 $obj2->printHello() 实现的。
?>

方法的访问控制

类中的方法存在公有、私有和受保护这三种定义方式。若未设置这些关键字,那么该方法就会默认是公有。

MyPublic();
        $this->MyProtected();
        $this->MyPrivate();
    }
}
$myclass = new MyClass;
这行代码可以被正常执行,即执行了 $myclass 的 MyPublic 方法。
这行代码会产生一个致命错误,它调用了 $myclass 的 MyProtected 方法。
这行代码会导致一个致命错误,它调用了 $myclass 的 MyPrivate 方法。
公有、受保护、私有这三种权限下都可以执行 $myclass->Foo(); 这个操作。 可以执行 $myclass->Foo(); 的权限包括公有、受保护和私有。 $myclass->Foo(); 这个操作在公有、受保护、私有权限下都能被执行。
/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // 此方法为公有
    function Foo2()
    {
        $this->MyPublic();
        $this->MyProtected();
这行代码会调用一个名为 MyPrivate 的方法,执行后会产生一个致命错误。
    }
}
$myclass2 = new MyClass2;
这行代码可以被正常执行,即 $myclass2->MyPublic();
公有的和受保护的可以执行 $myclass2->Foo2(); ,然而私有的不行。
class Bar 
{
    public function test() {
        $this->testPrivate();
        $this->testPublic();
    }
此函数为 public 函数,其名为 testPublic()。该函数用于执行特定的测试操作或功能。它在程序的某个部分被调用,以验证相关的代码逻辑或数据处理过程。
        echo "Bar::testPublic\n";
    }
    
这个函数是私有的,名为 testPrivate。它主要用于执行特定的操作或功能,在类的内部被调用,外部无法直接访问。它的作用可能是对类的内部状态进行处理、验证数据或执行一些特定的逻辑。
        echo "Bar::testPrivate\n";
    }
}
class Foo extends Bar 
{
    public function testPublic() {
        echo "Foo::testPublic\n";
    }
    
    private function testPrivate() {
        echo "Foo::testPrivate\n";
    }
}
$myFoo = new foo();
$myFoo 执行了一个方法;这个方法是 test;Bar 类中有一个名为 testPrivate 的方法被调用了。
                // Foo::testPublic
?>

接口

使用接口,能够明确指定某一个类需要去实现哪些方法,然而却无需对这些方法的具体内容进行定义。

接口通过 interface 关键字来进行定义,如同定义一个标准的类。并且在接口中定义的所有方法都是空的。

接口中定义的所有方法都必须是公有,这是接口的特性。

实现一个接口需使用 implements 操作符。类必须将接口中定义的所有方法都予以实现,不然就会出现一个致命错误。类能够实现多个接口,多个接口的名称用逗号进行分隔。

vars[$name] = $var;
    }
  
这个函数的功能是获取 HTML 内容,其参数为 $template 。
    {
2. 取出$value。
$template 被进行了替换操作,将其中的 '{'. $name. '}' 替换为了 $value ,替换后的结果仍为 $template 。
        }
 
        return $template;
    }
}

常量

可以将在类里始终保持不变的值规定为常量。在对常量进行定义和使用的时候,无需使用 $ 这个符号。

常量的值必须是固定不变的。它不能是变量,不能是类的属性,不能是数学运算的结果,也不能是函数的调用。

从 PHP 5.3.0 开始,能够利用一个变量来进行类的动态调用。然而,这个变量的值不可以是关键字,像 self、parent 或者 static 这些。

实例

showConstant();
输出 $class::constant 并换行。自 PHP 5.3.0 开始有此操作。
?>

抽象类

一个类如果里面存在至少一个被声明为抽象的方法,那么这个类就必须被声明为抽象的。

定义为抽象的类不能被实例化。

抽象的方法被定义后,只是声明了它的调用方式也就是参数,而无法定义其具体的功能实现。

当继承一个抽象类时,子类需要定义父类中的所有抽象方法。并且,这些方法的访问控制要和父类中的相同或者更为宽松。比如某个抽象方法被声明为受保护的,那么子类中实现的方法就应当声明为受保护的或者公有的,而不能将其定义为私有的。

getValue() . PHP_EOL;
    }
}
ConcreteClass1 继承自 AbstractClass 。
{
这个函数用于获取值。它在内部进行一些特定的操作来获取所需的值。具体的获取方式在函数的实现中有所体现。
        return "ConcreteClass1";
    }
这个函数名为 prefixValue,它接受一个参数 $prefix,用于执行某种与前缀相关的操作。 它会根据传入的前缀进行特定的处理或计算,以得到相应的结果。 这个函数在特定的代码逻辑中被调用,以处理与前缀相关的任务。 它的主要作用是对传入的前缀进行处理,以满足程序的需求。
返回“{$prefix}具体类 1”;
    }
}
ConcreteClass2 以 AbstractClass 为基类进行扩展。
{
    public function getValue() {
        return "ConcreteClass2";
    }
    public function prefixValue($prefix) {
返回“{$prefix}具体类 2”;
    }
}
$class1 = new ConcreteClass1;
$class1->printOut();
输出换行符。
$class2 = new ConcreteClass2;
$class2->printOut();
输出 $class2 调用 prefixValue 方法并传入 'FOO_' 后的值并换行。
?>

执行以上代码,输出结果为:

ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

此外,子类方法可以包含父类抽象方法中不存在的可选参数。

子类定义了一个可选参数,而父类的抽象方法声明中没有这个参数,这种情况下也是可以正常运行的。

prefixName("Pacman"), "\n";
输出该类的前缀名称“Pacwoman”,然后换行。
?>

输出结果为:

Mr. Pacman
Mrs. Pacwoman

Static 关键字

声明类的属性或方法为 static(静态),这样就能够在不实例化类的情况下直接对其进行访问。

静态属性无法通过一个类已实例化的对象去进行访问。然而,静态方法是可以被这样访问的。

静态方法无需通过对象就能被调用。因此,在静态方法中,伪变量 $this 是不可用的。

静态属性不可以由对象通过 -> 操作符来访问。

从 PHP 5.3.0 开始,能够利用一个变量来实现对类的动态调用。然而,这个变量的值不可以是关键字 self、parent 或者 static。

staticValue() . PHP_EOL;
?>    

执行以上程序,输出结果为:

foo
foo

Final 关键字

PHP 5 增添了一个 final 关键字。若父类中的方法被标注为 final,那么子类就没办法对该方法进行覆盖。倘若一个类被标识为 final,就不能被其他类所继承。

以下代码执行会报错:


调用父类构造方法

PHP 不会在子类的构造方法里自动去调用父类的构造方法。若要执行父类的构造方法,就需要在子类的构造方法中调用 parent::__construct() 。


执行以上程序,输出结果为:

BaseClass 类中构造方法
BaseClass 类中构造方法
SubClass 类中构造方法
BaseClass 类中构造方法

你可能想看:
« 上一篇
下一篇 »

相关推荐

php实时推送,php实地培训

2026年10月05日

53阅读

php乱码出现问号的原因,php乱码出现问号的原因有哪些

2026年10月05日

44阅读

php一句话木马,一句话木马ctf

2026年10月05日

48阅读

php获取数组长度,php中如何获取数组的长度

2026年10月05日

50阅读

php面试题库及答案,php程序员面试真题库

2026年10月05日

47阅读

phpcontent-type修改,php源码二次修改需要多少钱

2026年10月05日

42阅读