ホームページ  >  記事  >  バックエンド開発  >  PHP コードのオブジェクト指向の基本 1

PHP コードのオブジェクト指向の基本 1

WBOY
WBOYオリジナル
2016-06-23 13:38:57975ブラウズ

この記事は初心者には適していません。PHP をある程度理解している人は、PHP のオブジェクト指向機能の一部を補足または復習するために読むことができます。


1. オブジェクト指向とは何ですか?

多少は分かっているのですが、開発でしかオブジェクト指向とは何かとしか言えない気がします。言ってるだけ無駄ですが、PHPはWeb開発で使われることが多いので、オブジェクト指向を使わなくても十分に動作します。このインターフェースを見たとき、まず最初にオブジェクトを 1 つずつ作成し、各オブジェクト間の関係を決定し、最終的にそれらを発展させます。

クラスとは何ですか?オブジェクトとは何ですか?

クラスはセットの抽象化です。それはどのセットですか?同様のプロパティと操作を持つオブジェクトのコレクションです。

オブジェクトは、特定のクラスの特定のインスタンスです。

卒業したら、面接官に暗唱するかもしれませんが、今はまだ自分の理解が本の文章と同じくらい下品だと感じていますが、少なくともこの 2 つを表現するのに自分の脳細胞に頼る必要はなくなりました。定義。


2. php のクラス構造

php のクラスもアクセス制御文字であり、属性とメソッドもあります。

class Person {    private $name = "PersonName";    public static $gender = "PersonGender";        public function test(){        echo $this->name, '<br />';    }};


3. コンストラクター

コンストラクターの名前は __construct です。コンストラクターでは、次の点を強調したいと思います。

1. PHP は他の言語とは異なります。または java) この方法では、サブクラスをインスタンス化するときに親クラスのコンストラクターが自動的に呼び出されます。PHP では、ここで継承が関係するため、最初に継承を確認することができます。

class Person{	public funciton __construct(){		echo 'Person construct<br />';	}};class Teacher extends Person{	public function __construct(){		//parent::__construct();		echo 'Teacher construct<br />';	}};$t1 = new Teacher; //生成Teacher对象

操作結果:

Teacher コンストラクト

サブクラスの生成時に親クラスの一部のデータを初期化したい場合は、親クラスのコンストラクターを手動で呼び出してコメント行を開く必要があります。


2. クラス内に異なるパラメーターを持つ 2 つのコンストラクターを記述することはできません。

これには php のいくつかの規制が含まれます。他の言語では、次の記述は正しいです:

class Person{	public funciton __construct(){		echo 'Person construct<br />';	}	public function __construct($param){		echo 'Person with param construct<br />';	}};



しかし、php は弱い言語タイプであるため、これは許可されません。型の制限に非常に敏感で、__call および func_get_args 関数メカニズムを提供するため、次の方法で実装できます:

class Person{	public function __construct(){		$param = func_get_arg(); //获取参数数据		$param_num = func_num_args(); //获取参数个数		if($param_num == 0){		}else if($param_num == 1){			if(is_array($param[0])){				//...			}		}else{			//...		}	}};



3. デストラクター

ここでデストラクターが使用されます。インスタンス オブジェクトが終了すると、自動的に呼び出される関数は、インスタンスの終了を完全に終了するためにメモリを解放するステートメントを記述することができます。これは、継承関係がある場合、親クラスのデストラクターを手動で呼び出す必要があることと同じです。クラス デストラクターは 1 つだけです。


4. 制御アクセス文字

public: パブリック アクセス文字。このプロパティまたはメソッドは、クラス内、サブクラス内、およびクラス外からアクセスできます。

protected: 保護されたアクセサー。このプロパティまたはメソッドはクラスとそのサブクラス内でのみアクセスでき、クラス外からはアクセスできません。

private: このクラス内でのみアクセスできるプライベート アクセス シンボル。継承したりオーバーロードしたりすることはできません。


5. マジック メソッド __get と __set

これら 2 つのメソッドの機能: 保護されたプロパティとプライベート プロパティにアクセスするためのアクセサー。これにより、検証クラスの外部から受信したデータの安全性と合理性が保証されます。

__set メソッドは 2 つのパラメータを受け取ります。1 つ目は属性名で、2 つ目は割り当てられる新しい値です。

__get メソッドは 1 つのパラメータ、属性名を受け取ります。


1. パブリック属性は、クラス外の属性を変更するためのサービスを提供できます。したがって、パブリック属性の場合、__get および __set プロセスは実行されません。

class D{    public $name = 'D name';    protected $gender = 'male';    private $age = 18;    public function __set($name, $value){        echo '__set<br />';	//if(in_array($name, ['name', 'gender', 'age']))	$this->$name = $value;    }    public function __get($name){        echo '__get<br />';		//if(!in_array($name, ['name', 'gender', 'age'])) return NULL;        return $this->$name;    }};



运行结果:
new D name //name为public属性,不会走get和set__set__getnew D gender__set__getnew D age


2. データ検証機能を追加し、コメントを開いて検証することもできます。

3. 2 つのメソッドにはパブリック アクセスが必要です。そうでないとエラーが発生します。これら 2 つの関数の機能から、パブリック アクセス制御が必要な理由を想像するのは難しくありません。


6. 継承

最後に、継承がなければ、すべてのクラスはゴミになります。 . この継承機能を詳しく見てみましょう。

継承の話はやめましょう。記事の冒頭に継承の小さな例があります。

相続が発生するとどのような問題が起こるのでしょうか?考えてみてください、B が A を継承すると... とても想像できません...

1. コンストラクター、心配しないでください。これは 2 つのクラスのコンストラクターに相当しますが、もあります。したがって、上記のように、必要に応じて親クラスのコンストラクターを手動で呼び出すことができます。

2. 一方向の継承。サブクラスは親クラスから継承できますが、親クラスはサブクラスから機能を継承できません。

3. 重载,一提到php的重载就特别别扭,因为他的重载放到其他语言里叫做重写overwrite,我还是习惯将这个特性说为重写,大家随便。

<1>public重载:

class E{    public $attr1 = 'E attr1 value';    public function oper1(){        echo 'E oper1<br />';        echo 'attr1 value = ', $this->attr1, '<br />';    }};class F extends E{    public $attr1 = 'F attr1 value';    public function oper1(){        //parent::oper1();        echo 'F oper1<br />';        echo 'attr1 value = ', $this->attr1, '<br />';    }};$f = new F;$f->oper1();

运行结果:

F oper1
attr1 value = F attr1 value


F继承了E并且重写了E的attr1和oper1,因此,在调用oper1时,$this->attr1显示F attr1 value,如果打开注释parent::oper1调用父类的Oper1方法,运行结果如下:

E oper1
attr1 value = F attr1 value //attr1属性已经被子类重写的attr1属性覆盖
F oper1
attr1 value = F attr1 value

可以看出子类重写父类的属性和方法后,会覆盖父类相应的属性和方法。


<2>private重载

class E{    private $attr1 = 'E attr1 value';    public function oper1(){        echo 'E oper1<br />';        echo 'attr1 value = ', $this->attr1, '<br />';    }};class F extends E{    public $attr1 = 'F attr1 value';    public function oper1(){        parent::oper1();        echo 'F oper1<br />';        echo 'attr1 value = ', $this->attr1, '<br />';    }};$f = new F;$f->oper1();
以上代码只变动了一处地方,就是把父类$attr1的访问属性变成private,那重载机制如何执行呢?先看运行结果:

E oper1
attr1 value = E attr1 value //父类私有的属性
F oper1
attr1 value = F attr1 value


之前我们说过,private属性和方法子类是继承不了的,这种情况,遵循一个原则:

private属性在那个类里调用的,就显示哪个类里的属性值。

示例中的parent::oper1方法调用的是E类的oper1方法,在E的oper1方法内又调用了$this->attr1,attr1是private并没有被子类继承,因此,调用的就是类E里的attr1属性值。


<3>protected重载与public重载一致


<4>类属性的继承

class G{    public static $attr1 = 'G attr1 value';    public function oper1(){        echo 'G oper1<br />';        echo 'attr1 value = ', self::$attr1, '<br />';    }};class H extends G{    public static $attr1 = 'H attr1 value';    public function oper1(){        parent::oper1();        echo 'H oper1<br />';        echo 'attr1 value = ', self::$attr1, '<br />';    }};$h = new H;$h->oper1();

运行结果:

G oper1
attr1 value = G attr1 value
H oper1
attr1 value = H attr1 value

其实不管G类的attr1属性是public还是private,结果都一样。

个人是这么理解的,类属性可以继承,但谈不上重载,那关于子类调用父类的属性也有一规则:

self或者parent只代表本类,因此,根据这一原则可以断定,属性的值一定是本类属性的值,与子类无关。(特殊情况时php的静态延迟加载机制)。


七.静态延迟加载

既然已经提到了静态延迟加载,就趁热打铁讲一下,H和G的例子大家已经看了,那我就是想要在子类中调用父类的东东怎么办?静态延迟加载就是解决这个问题,请看两个示例:

示例1:

还是H和G类的例子

class G{    public static $attr1 = 'G attr1 value';    public function oper1(){        echo 'G oper1<br />';        echo 'attr1 value = ', static::$attr1, '<br />';    }};class H extends G{    public static $attr1 = 'H attr1 value';    public function oper1(){        parent::oper1();        echo 'H oper1<br />';        echo 'attr1 value = ', self::$attr1, '<br />';    }};$h = new H;$h->oper1();
运行结果:

G oper1
attr1 value = H attr1 value
H oper1
attr1 value = H attr1 value

上面代码只是将G类里的self::$attr1改写成了static::$attr1,运行结果就不一样了


示例2:

class I {    public static function who(){        echo __CLASS__, '<br />';    }    public static function test(){        static::who();    }};class J extends I{    public static function who(){        echo __CLASS__,'<br />';    }};

运行结果:

J


通过这两个例子,可以好好的领悟一下static的静态延迟绑定。


写的有点多,主要是因为一牵扯继承就停不下来....面向对象还有一些只是点,后面有时间再补上吧...谢谢,如若有错误的地方,敬请大家指出,随时更正,谢谢!!



声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。