PHP面向对象三大特点学习(充分理解抽象、封装、继承、多态)_php技巧
面象对向的三大特点:封装性、继承性、多态性 首先简单理解一下抽象:
我们在前面定义一个类的时候,实际上就是把一类事物共有的属性和行为提取出来,形成一个物理模型(模版),这种研究问题的方法称为抽象
一、封装性
封装就是把抽取出来的数据和对数据的操作封装在一起,数据被保护在内部,程序的其他部分只有被授权的操作(方法)才能对数据进行操作。
php提供了三种访问控制修饰符
public 表示全局,本类内部,类外部,子类都可以访问
protected 表示受保护的,只有本类或子类可以访问
private 表示私有的,只有本类内部可以访问
以上三种修饰符既可以修饰方法也可以修饰属性(变量),方法如果没有访问修饰符则默认是public,成员属性必须指定访问修饰符,在PHP4中也有这种写法 var $name,表示公开属性,不推荐这种写法
例:
class Person{
public $name;
protected $age;
private $salary;
function __construct($name,$age,$salary){
$this->name=$name;
$this->age=$age;
$this->salary=$salary;
}
public function showinfo(){
//这表示三个修饰符都可以在本类内部使用
echo $this->name."||".$this->age."||".$this->salary;
}
}
$p1=new Person('张三',20,3000);
//这里属于类外部,那么如果用下面的方法访问age和salary都会报错
// echo $p1->age; echo$p1->salary;
?>
那么现在就想在外部访问protected和private的元素和方法该怎么办? 通常做法是通过public函数去访问这些变量 格式:
public function setxxxx($val){
$this->xxxx=$val;
}
public function getxxxx(){
return $this->xxxx;
}
这里带set和get只是为了识别方便,并非必要
如:
public function getsalary(){
return $this->salary; //扩展:这里可以调用一些方法,如判断用户名等,正确才给访问
}
在外部就可以通过 echo $p1->getsalary();
如果要访问 protected和private也可以使用以下方法,但不推荐使用,只要了解即可
__set() 和 __get()
__set()对protected或private属性进行赋值操作
__set($name,$val);
__get()获取 protected 或 private的值
__get($name);
如:
class testa{
protected $name;
//使用__set()来管理所有属性
public function __set($pro_name,$pro_val){
//上面$pro_name和$pro_val可自定义
//下面$this->pro_name为既定,不可更改
$this->pro_name=$pro_val;
}
//使用__get()来获取所有属性值
public function __get($pro_name){
if(isset($pro_name)){
return $this->pro_name;
} else {
return null;
}
}
}
$n1=new testa();
//正常情况,类外部是不能访问protected属性的,但是用了上面的方法就可以对它们进行操作
$n1->name='小三';
echo $n1->name;
?>
//以上代码看懂就行,不推荐使用
二、继承性
先看一个例子:
class Pupil{
public $name;
protected $age;
public function getinfo(){
echo $this->name.'||'.$this->age;
}
public function testing(){
echo 'this is pupil';
}
}
class Graduate{
public $name;
protected $age;
public function getinfo(){
echo $this->name.'||'.$this->age;
}
public function testing(){
echo 'this is Graduate';
}
}
?>
从上面的例子可以看出,当多个类有很多共同属性和方法时,代码的复用性不高,代码冗余,思考css中的处理方法
解决方法 :继承
class Students{
public $name;
public $age;
public function __construct($name,$age){
$this->name=$name;
$this->age=$age;
}
public function showinfo(){
echo $this->name.'||'.$this->age;
}
}
class Pupil extends Students{
function testing(){
echo 'Pupil '.$this->name.' is testing';
}
}
class Graduate extends Students{
function testing(){
echo 'Graduate '.$this->name.' is testing';
}
}
$stu1=new Pupil('张三',20);
$stu1->showinfo();
echo '
';
$stu1->testing();
?>
从上面可以看出,继承就是一个子类(Subclass)通过 extends 父类 把父类(BaseClass)中的public 和 protected 的属性和方法继续下来,不能继承private属性和方法
语法结构:
class 父类名{}
class 子类名 extends 父类名{}
细节:
1、一个子类只能继承一个父类(这里指直接继承);如果希望继承多个类的属性和方法,可以使用多层继承
例:
class A{
public $name='AAA';
}
class B extends A{
public $age=30;
}
class C extends B{}
$p=new C();
echo $p->name;//这里会输出AAA
?>
2、在创建某个子类对象时,默认情况下不会自动调用其父类的构造函数
例:
class A{
public function __construct(){
echo 'A';
}
}
class B extends A{
public function __construct(){
echo 'B';
}
}
$b=new B();//这里会优先输出B中的构造方法,如果B中没有构造方法才会输出A中的
3、在子类中如果需要访问父类的方法(构造方法、成员方法 方法的修饰符为protected或private),那么可以使用 父类::方法名 或者 parent::方法名 来完成【这里parent和以前提到的self都均为小写,大写报错】
class A{
public function test(){
echo 'a_test';
}
}
class B extends A{
public function __construct(){
//两种方法都行
A::test();
parent::test();
}
}
$b=new B();
5、如果一个子类(派生类)的方法与父类的方法完全一样时(public,protected),我们称为方法覆盖或方法重写(override),看下面的多态性
三、多态性
例 :
class Animal{
public $name;
public $price;
function cry(){
echo 'i don\'t know';
}
}
class Dog extends Animal{
//覆盖、重写
function cry(){
echo 'Wang Wang!';
Animal::cry();//这里不会报错,能正确执行父类的cry();
}
}
$dog1=new Dog();
$dog1->cry();
?>
小结:
1、当一个父类知道所有的子类都有一个方法,但是父类不能确定该方法如何写,可以让子类去覆盖它的方法,方法覆盖(重写),必须要求子类的方法名和参数个数完全一致
2、如果子类要去调用父类的某个方法(protected/public),可以使用 父类名::方法名 或者 parent::方法名
3、在实现方法重写的时候,访问修饰符可以不一样,但是子类方法的访问权限必须大于等于父类方法的访问权限(即不能缩小父类方法的访问权限)
如 父类public function cry(){} 子类 protected function cry(){} 则会报错
但是子类的访问权限可以放大,如:
父类private function cry(){} 子类 protected function cry(){} 可以正确执行
扩展:
方法重载(overload)
基本概念:函数名相同,但参数的个数或参数的类型不同,达到调用同一个函数,可以区分不同的函数
在PHP5中虽然也支持重载,但是和其它语言还是有很大区别的,php中不能定义多个同名函数
PHP5中提供了强大的“魔术”函数,使用这些魔术函数,我们可以做到函数重载,
这里我们要到到 __call,当一个对象调一个方法时,而该方法不存在,则程序会自动调用__call
【官方不推荐使用】
PHP中有以下几个魔术常量:__LINE__ __FILE__ __DIR__ __FUNCTION__ __CLASS__ 等
例:
class A{
function test1($p){
echo 'test1
';
}
function test2($p){
echo 'test2
';
}
function __call($method,$p){
//这里$p为数组,上面两个变量名可自定义
if($method == 'test'){
if(count($p)==1){
$this->test1($p);
} else if(count($p)==2){
$this->test2($p);
}
}
}
}
$a=new A();
$a->test(5);
$a->test(3,5);
?>

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック











関数の継承では、「基底クラス ポインター」と「派生クラス ポインター」を使用して継承メカニズムを理解します。基底クラス ポインターが派生クラス オブジェクトを指す場合、上方変換が実行され、基底クラスのメンバーのみにアクセスされます。派生クラス ポインターが基本クラス オブジェクトを指す場合、下向きキャストが実行される (安全ではない) ため、注意して使用する必要があります。

仮想基本クラスは、追加の vtable を作成せずに複数の基本クラスからの継承を許可することで、vtable のメモリ オーバーヘッドを最適化します。最適化されたコードでは、形状基本クラスに仮想関数テーブルがなくなり、円クラスと長方形クラスが同じ仮想関数テーブルを共有するため、メモリ消費量が削減されます。

4月17日の当サイトのニュースによると、TrendForceは最近、Nvidiaの新しいBlackwellプラットフォーム製品に対する需要は強気で、2024年にはTSMCのCoWoSパッケージング総生産能力が150%以上増加すると予想されるレポートを発表した。 NVIDIA Blackwell の新しいプラットフォーム製品には、B シリーズ GPU と、NVIDIA 独自の GraceArm CPU を統合する GB200 アクセラレータ カードが含まれます。 TrendForce は、サプライチェーンが現在 GB200 について非常に楽観的であることを確認しており、2025 年の出荷台数は 100 万台を超え、Nvidia のハイエンド GPU の 40 ~ 50% を占めると予想されています。 Nvidiaは今年下半期にGB200やB100などの製品を提供する予定だが、上流のウェーハパッケージングではさらに複雑な製品を採用する必要がある。

継承とポリモーフィズムはクラスの結合に影響します。派生クラスは基本クラスに依存するため、継承により結合が増加します。ポリモーフィズムにより、オブジェクトは仮想関数と基本クラス ポインターを通じて一貫した方法でメッセージに応答できるため、結合が軽減されます。ベスト プラクティスには、継承を控えめに使用すること、パブリック インターフェイスを定義すること、基本クラスへのデータ メンバーの追加を回避すること、依存関係の注入を通じてクラスを分離することが含まれます。ポリモーフィズムと依存性注入を使用して銀行口座アプリケーションの結合を軽減する方法を示す実践的な例。

このWebサイトは7月9日、AMD Zen5アーキテクチャの「Strix」シリーズプロセッサには2つのパッケージングソリューションがあり、小型のStrixPointはFP8パッケージを使用し、StrixHaloはFP11パッケージを使用すると報じた。出典: videocardz 出典 @Olrak29_ 最新の事実は、StrixHalo の FP11 パッケージ サイズが 37.5mm*45mm (1687 平方ミリメートル) であり、これは Intel の AlderLake および RaptorLake CPU の LGA-1700 パッケージ サイズと同じであるということです。 AMD の最新の Phoenix APU は、サイズ 25*40mm の FP8 パッケージング ソリューションを使用しています。これは、StrixHalo の F

継承エラーのデバッグのヒント: 正しい継承関係を確認します。デバッガーを使用してコードをステップ実行し、変数値を調べます。仮想修飾子を正しく使用してください。隠れた相続によって引き起こされる相続ダイアモンド問題を調べてください。抽象クラスに実装されていない純粋仮想関数がないか確認します。

コードをカプセル化することにより、C++ 関数は GUI 開発効率を向上させることができます。 コードのカプセル化: 関数はコードを独立した単位にグループ化し、コードの理解と保守を容易にします。再利用性: 関数はアプリケーション間で再利用できる共通の機能を作成し、重複やエラーを削減します。簡潔なコード: カプセル化されたコードにより、メイン ロジックが簡潔になり、読みやすく、デバッグしやすくなります。

C++ 関数の継承は、次の状況では使用しないでください。 派生クラスが異なる実装を必要とする場合、異なる実装を持つ新しい関数を作成する必要があります。派生クラスが関数を必要としない場合は、空のクラスとして宣言するか、プライベートの未実装の基本クラス メンバー関数を使用して関数の継承を無効にする必要があります。関数が継承を必要としない場合は、コードの再利用を実現するために他のメカニズム (テンプレートなど) を使用する必要があります。
