English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

PHP 基礎チュートリアル

PHP 高級チュートリアル

PHP と MySQL

PHP リファレンスマニュアル

PHPのオブジェクト指向

在面向对象的程序设计(英語:Object-oriented programming,缩写:OOP)中,对象是一个由信息及对信息进行处理的描述所组成的整体,是对现实世界的抽象。

在现实世界里我们所面对的事情都是对象,如计算机、电视机、自行车等。

对象的主要三个特性:

  • 对象的行为:可以对 对象施加那些操作,开灯,关灯就是行为。

  • 对象的形态:当施加那些方法是对象如何响应,颜色,尺寸,外型。

  • 对象的表示:对象的表示就相当于身份证,具体区分在相同的行为与状态下有什么不同。

例えば、Animal(動物)は抽象クラスであり、具体的には犬や羊に具体化できます。犬や羊は具体的なオブジェクトであり、色の属性があり、書き込み、走行などの行動状態があります。

面向对象内容

  • − 一つの抽象的な特徴を定義します。クラスの定義にはデータの形式とデータに対する操作が含まれます。

  • 对象 − クラスの例です。

  • メンバーベクトル − クラスの内部に定義された変数であり、その値は外部からは見えませんが、メンバ関数を通じてアクセスできます。クラスがオブジェクトとして例示された後、この変数はオブジェクトの属性と呼ばれます。

  • メンバーファンクション − クラスの内部に定義され、オブジェクトのデータへのアクセスに使用されます。

  • 継承 − 継承性とは、子クラスが自動的に親クラスのデータ構造とメソッドを共有するメカニズムであり、クラス間の関係の一種です。クラスの定義と実装を行う際には、既存のクラスの上に基づいて行うことができ、既存のクラスで定義された内容を自分の内容として取り入れ、いくつかの新しい内容を追加することができます。

  • 父クラス − クラスが他のクラスに継承される場合、そのクラスを親クラス、もしくは基底クラス、または超クラスと呼びます。

  • 子クラス − クラスが他のクラスを継承すると、そのクラスを子クラス、もしくは派生クラスと呼びます。

  • 多態 − 多態性とは、同じ関数やメソッドがさまざまなタイプのオブジェクトに適用され、異なる結果を得ることを指します。異なるオブジェクトが同じメッセージを受け取ると、異なる結果が得られる現象を多態性と呼びます。

  • 重载 − 簡単に言えば、同じ名前の関数やメソッドが異なるパラメータリストを持つ場合があります。このような同名異パラメータの関数やメソッド間では、互いにオーバーロード関数やメソッドと呼びます。

  • 抽象性 − 抽象性とは、一貫したデータ構造(属性)と行動(操作)を持つオブジェクトをクラスとして抽象化することを指します。クラスはこのような抽象であり、アプリケーションに関連する重要な性質を反映し、他の関連のない内容を無視します。クラスの分類は主観的ですが、具体的なアプリケーションに関連する必要があります。

  • 封装 − 封装とは、現実世界に存在するある客体的属性と行動を結びつけ、一つの論理ユニットに配置することを指します。

  • 構造関数 − オブジェクトの作成時にオブジェクトメンバ変数を初期化するために主に使用されます。これにより、オブジェクトのメンバ変数に初期値が設定され、new演算子と一緒にオブジェクトの作成文に使用されます。

  • デストラクタ − 析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做"清理善后" 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。

− デストラクタ(destructor)はコンストラクタの逆で、オブジェクトがそのライフサイクルを終了した場合(例えば、オブジェクトがいる関数が呼び出された後に)、システムが自動的にデストラクタを実行します。デストラクタは「清算」の作業(例えば、オブジェクトの作成時にnewでメモリ空間を確保した場合、退出前にデストラクタでdeleteを使用して解放するべきです)に使用されます。

以下の図では、Carクラスを通じて3つのオブジェクトを作成しました:Mercedes、Bmw、およびAudi。
$mercedes = new Car();
$bmw = new Car();

$audi = new Car();

PHPクラス定義

<?php
PHPでクラスを定義する通常の文法は以下の通りです:
  class phpClass {1;
  class phpClass {2 var $var
  
  = "constant string";1function myfunc ($arg2) {
     , $arg
  }
  , $arg
}
?>

[..]

  • 以下に説明します: クラスの使用 class

  • キーワードの後にクラス名を追加して定義します。

  • クラスの変数はクラス名の後の大括弧({})内で定義できます。 var で宣言し、変数には初期値を設定することもできます。

  • 関数の定義はPHPの関数の定義に似ていますが、関数はこのクラスやそのインスタンス化されたオブジェクトからのみアクセスできます。

<?php
class Site {
  /* メンバーベクトル */
  var $url;
  var $title;
  
  /* メンバーファンクション */
  function setUrl($par){
     $this->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 演算子を使ってこのクラスのオブジェクトをインスタンス化します:

$w3codebox = new Site;
$taobao = new Site;
$google = new Site;

上記のコードでは、3つのオブジェクトを作成しました。3つのオブジェクトはそれぞれ独立しており、次にメンバーファンクションとメンバーベクトルのアクセス方法を見てみましょう。

メンバーファンクションの呼び出し

オブジェクトをインスタンス化した後、オブジェクトを呼び出してメンバーファンクションを使用できます。オブジェクトのメンバーファンクションは、そのメンバーベクトルのみを操作できます:

// メンバーファンクションを呼び出し、タイトルとURLを設定します
$w3codebox->setTitle( "基礎教材網" );
$taobao->setTitle('淘宝');
$google->setTitle( "Google 検索" );
$w3codebox->setUrl( 'www.w3>setUrl( 'codebox.com' );
$taobao->setUrl('www.taobao.com');
$google->setUrl( 'www.google.com' );
// メンバ関数を呼び出して、タイトルとURLを取得します
$w3codebox->getTitle();
$taobao->getTitle();
$google->getTitle();
$w3codebox->getUrl();
$taobao->getUrl();
$google->getUrl();

完全なコードは以下の通りです:

オンラインサンプル

<?php
class Site {
  /* メンバーベクトル */
  var $url;
  var $title;
  
  /* メンバーファンクション */
  function setUrl($par){
     $this->url = $par;
  }
  
  function getUrl(){
     echo $this->url . PHP_EOL;
  }
  
  function setTitle($par){
     $this->title = $par;
  }
  
  function getTitle(){
     echo $this->title . PHP_EOL;
  }
}
$w3codebox = new Site;
$taobao = new Site;
$google = new Site;
// メンバーファンクションを呼び出し、タイトルとURLを設定します
$w3codebox->setTitle( "基礎教材網" );
$taobao->setTitle( "天猫商城" );
$google->setTitle( "Google 検索" );
$w3codebox->setUrl( 'www.w3>setUrl( 'codebox.com' );
$taobao->setUrl( 'www.tmall.com' );
$google->setUrl( 'www.google.com' );
// メンバ関数を呼び出して、タイトルとURLを取得します
$w3codebox->getTitle();
$taobao->getTitle();
$google->getTitle();
$w3codebox->getUrl();
$taobao->getUrl();
$google->getUrl();
?>

上記のコードを実行すると、出力結果は以下のようになります:

基礎教材網
天猫商城
Google 検索
ja.oldtoolbag.com
www.tmall.com
www.google.com

PHPの構造関数

構造関数は特別なメソッドです。主にオブジェクトを生成する際にオブジェクトを初期化するために使用され、オブジェクトのメンバ変数に初期値を設定します。new演算子と一緒に使用されます。

PHP 5 開発者がクラス内で構造関数としてメソッドを定義することができます。以下の形式で構文されています:

void __construct ([ mixed $args [, $... ]]] )

上記の例では、$url と $title 変数を初期化するために、構造関数を使用することができます:

function __construct( $par1, $par2 ) {
   $this->url = $par1;
   $this->title = $par2;
}

今では setTitle と setUrl メソッドを呼び出す必要はありません:

オンラインサンプル

$w3codebox = new Site('ja.oldtoolbag.com', '基礎教材網');
$tmall= new Site('www.tmall.com', '天猫商城');
$google = new Site('www.google.com', 'Google 検索');
// メンバ関数を呼び出して、タイトルとURLを取得します
$w3codebox->getTitle();
$tmall->getTitle();
$google->getTitle();
$w3codebox->getUrl();
$tmall->getUrl();
$google->getUrl();

デストラクタ

デストラクタ(destructor)は、構造関数とは逆に、オブジェクトがそのライフサイクルを終了した場合(例えば、オブジェクトが属する関数が呼び出された後に)、システムが自動的にデストラクタを実行します。

PHP 5 構造関数の概念が導入されました。これは他の面向オブジェクト言語に似ており、以下の形式で構文されています:

void __destruct ( void )

<?php
class MyDestructableClass {
   function __construct() {
       print "構造関数\n";
       $this->name = "MyDestructableClass";
   }
   function __destruct() {
       print "破棄 " . $this->name . "\n";
   }
}
$obj = new MyDestructableClass();
?>

上記のコードを実行すると、出力結果は以下のようになります:

構造関数
MyDestructableClassを破棄

継承

PHPはキーワード extends PHPは多継承をサポートしておらず、以下の形式でクラスを継承します:

class Child extends Parent {
   // コード部分
}

例では、Child_SiteクラスがSiteクラスを継承し、機能を拡張しています:

<?php 
// サブクラスがサイトカテゴリを拡張
class Child_Site extends Site {
   var $category;
    function setCate($par){
        $this->category = $par;
    }
  
    function getCate(){
        echo $this->category . PHP_EOL;
    }
}

メソッドのリライト

親クラスから継承したメソッドが子クラスの要件を満たさない場合、そのメソッドを改写することができます。このプロセスはメソッドのオーバーライド(override)またはメソッドのリライトと呼ばれます。

例では、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(プライベート)などのキーワードを前に付けることで実現されます。

  • public(パブリック):パブリックなクラスメンバーはどこでもアクセスできます。

  • protected(プロテクテッド):プロテクテッドなクラスメンバーは、その自身、そのサブクラス、および親クラスでアクセスできます。

  • private(プライベート):プライベートなクラスメンバーは、その定義されたクラスのみでアクセスできます。

属性のアクセス制御

クラス属性はpublic、protected、privateのいずれかで定義しなければなりません。varで定義すると、publicとみなされます。

<?php
/**
 * Define MyClass
 */
class MyClass
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';
    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}
$obj = new MyClass();
echo $obj->public; // この行は通常通り実行できます
echo $obj->protected; // この行は致命的なエラーを発生させます
echo $obj->private; // この行は致命的なエラーを引き起こします
$obj->printHello(); // Public、Protected、およびPrivateを输出
/**
 *MyClassを定義します2
 */
class MyClass2 extends MyClass
{
    // publicとprotectedは再定義できますが、privateはできません
    protected $protected = 'Protected'2';
    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}
$obj2 = new MyClass2();
echo $obj2->public; // この行は通常通り実行できます
echo $obj2->private; // 未定義 private
echo $obj2->protected; // この行は致命的なエラーを発生させます
$obj2->printHello(); // Public、Protectedを出力2 と 未定義
?>

メソッドのアクセス制御

クラス内のメソッドは公開、私有、または保護されたものとして定義できます。これらのキーワードが設定されていない場合、デフォルトで公開とみなされます。

<?php
/**
 * Define MyClass
 */
class MyClass
{
    // 公開されたコンストラクタを宣言します
    public function __construct() { }
    // 公開されたメソッドを宣言します
    public function MyPublic() { }
    // 保護されたメソッドを宣言します
    protected function MyProtected() { }
    // 私有的メソッドを宣言します
    private function MyPrivate() { }
    // このメソッドは公開されています
    function Foo()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate();
    }
}
$myclass = new MyClass;
$myclass->MyPublic(); // この行は通常通り実行できます
$myclass->MyProtected(); // この行は致命的なエラーを発生させます
$myclass->MyPrivate(); // この行は致命的なエラーを発生させます
$myclass->Foo(); // 公開、保護、私有的すべてを実行できます
/**
 * MyClassを定義します2
 */
class MyClass2 extends MyClass
{
    // このメソッドは公開されています
    function Foo2();
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate(); // この行は致命的なエラーを発生させます
    }
}
$myclass2 = new MyClass2;
$myclass2->MyPublic(); // この行は通常通り実行できます
$myclass2->Foo2(); // 公有と保護されたものは実行できますが、私有的のはできません
class Bar 
{
    public function test() {
        $this->testPrivate();
        $this->testPublic();
    }
    public function testPublic() {
        echo "Bar::testPublic\n";
    }
    
    private function 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 クラス内でインターフェースで定義されたすべてのメソッドを実装する必要があります。それがなければ致命的なエラーが発生します。クラスは複数のインターフェースを実装できます。インターフェース名をカンマで区切ります。

<?php
// 「iTemplate」インターフェースの宣言
interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}
// インターフェースの実装
class Template implements iTemplate
{
    private $vars = array();
  
    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }
  
    public function getHtml($template)
    {
        foreach($this->vars as $name => $value) {
            $template = str_replace('{'. $name .'}', $value, $template);
        }
 
        return $template;
    }
}

定数

クラス内で常に同じ値を持つ値を定数として定義できます。定数の定義と使用時に $ シンボルを使用する必要はありません。

定数の値は定数値でなければなりません。変数、クラス属性、数学演算の結果、または関数呼び出しではありません。

PHPから 5.3.0 以降、クラスを動的に呼び出すための変数を使用できますが、その変数の値はキーワード(self、parent、staticなど)ではありません。

<?php
class MyClass
{
    const constant = '常量值';
    function showConstant() {
        echo self::constant . PHP_EOL;
    }
}
echo MyClass::constant . PHP_EOL;
$classname = "MyClass";
echo $classname::constant . PHP_EOL; // から 5.3.0から
$class = new MyClass();
$class->showConstant();
echo $class::constant . PHP_EOL; // PHPから 5.3.0から
?>

抽象クラス

クラスには少なくとも1つのメソッドが抽象として宣言されている場合、そのクラスは抽象として宣言する必要があります。

抽象として定義されたクラスは、インスタンス化することはできません。

抽象として定義されたメソッドは、その呼び出し方法(パラメータ)のみを宣言し、具体的な機能実装を定義することはできません。

抽象クラスを継承する場合、サブクラスは親クラスのすべての抽象メソッドを定義する必要があります;また、これらのメソッドのアクセス制御は、親クラスと同じ(またはより広範)でなければなりません。たとえば、抽象メソッドが保護された宣言されている場合、サブクラスで実装されるメソッドは保護されたまたはパブリックに宣言される必要があります。プライベートには宣言することはできません。

<?php
abstract class AbstractClass
{
 // サブクラスがこれらのメソッドを定義する必要があります。
    abstract protected function getValue();
    abstract protected function prefixValue($prefix);
    // 通常のメソッド(抽象メソッドではない)
    public function printOut() {
        print $this->getValue() . PHP_EOL;
    }
}
class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }
    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass1";
    }
}
class ConcreteClass2 extends AbstractClass
{
    public function getValue() {
        return "ConcreteClass2";
    }
    public function prefixValue($prefix) {
        return "{$prefix}ConcreteClass2";
    }
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') . PHP_EOL;
$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') . PHP_EOL;
?>

上記のコードを実行すると、出力結果は以下のようになります:

ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2

さらに、サブクラスのメソッドは、親クラスの抽象メソッドに存在しないオプションパラメータを含むことができます。

たとえば、サブクラスがオプションパラメータを定義し、そのオプションパラメータを持たない親クラスの抽象メソッドの宣言では、正常に動作することもできます。

<?php
abstract class AbstractClass
{
    // 私たちの抽象メソッドは必要な引数のみを定義する必要があります。
    abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
    // サブクラスは、親クラスのシグネチャに存在しないオプションの引数を定義できます。
    public function prefixName($name, $separator = ".") {
        if ($name == "Pacman") {
            $prefix = "Mr";
        } elseif ($name == "Pacwoman") {
            $prefix = "Mrs";
        } else {
            $prefix = "";
        }
        return "{$prefix}{$separator} {$name}";
    }
}
$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
?>

出力結果は:

Mr. Pacman
Mrs. Pacwoman

Staticキーワード

クラス属性やメソッドをstatic(静的)として宣言することで、クラスを例示せずに直接アクセスすることができます。

静的属性はクラスの例示されたオブジェクトを通じてアクセスできません(ただし、静的メソッドはアクセスできます)。

静的メソッドはオブジェクトを通じて呼び出されないため、静的メソッドでは仮想変数$thisは使用できません。

静的属性はオブジェクトを通じてアクセスできません。 ->オペラータを使ってアクセスします。

PHPから 5.3.0から、変数を使って動的にクラスを呼び出すことができますが、その変数の値はself、parent、staticなどのキーワードではありません。

<?php
class Foo {
  public static $my_static = 'foo';
  
  public function staticValue() {
     return self::$my_static;
  }
}
print Foo::$my_static . PHP_EOL;
$foo = new Foo();
print $foo->staticValue() . PHP_EOL;
?>

以下のプログラムを実行すると、出力結果は:

foo
foo

Finalキーワード

PHP 5 新しいfinalキーワードが追加されました。親クラスのメソッドがfinalとして宣言された場合、そのメソッドは子クラスでオーバーライドできません。クラスがfinalとして宣言された場合、そのクラスは継承できません。

以下のコードを実行すると、エラーが発生します:

<?php
class BaseClass {
   public function test() {
       echo "BaseClass::test() called" . PHP_EOL;
   }
   
   final public function moreTesting() {
       echo "BaseClass::moreTesting() called"  . PHP_EOL;
   }
}
class ChildClass extends BaseClass {
   public function moreTesting() {
       echo "ChildClass::moreTesting() called"  . PHP_EOL;
   }
}
// エラーメッセージ 致命的エラー: Cannot override final method BaseClass::moreTesting()
?>

親クラスのコンストラクタを呼び出します

PHPは、子クラスのコンストラクタでは自動的に親クラスのコンストラクタを呼び出しません。親クラスのコンストラクタを実行するには、子クラスのコンストラクタで呼び出す必要があります。 parent::__construct()

<?php
class BaseClass {
   function __construct() {
       print "BaseClass クラスのコンストラクタ" . PHP_EOL;
   }
}
class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();  // 子クラスのコンストラクタは、自動的に親クラスのコンストラクタを呼び出すことができません
       print "SubClass クラスのコンストラクタ" . PHP_EOL;
   }
}
class OtherSubClass extends BaseClass {
    // BaseClass を継承するコンストラクタ
}
// BaseClass のコンストラクタを呼び出します
$obj = new BaseClass();
// BaseClass、SubClass のコンストラクタを呼び出します
$obj = new SubClass();
// BaseClass のコンストラクタを呼び出します
$obj = new OtherSubClass();
?>

以下のプログラムを実行すると、出力結果は:

BaseClass クラスのコンストラクタ
BaseClass クラスのコンストラクタ
SubClass クラスのコンストラクタ
BaseClass クラスのコンストラクタ