PHPerの為のPython入門 - クラス


[関数編](http://qiita.com/odoku/items/e1faf1cb8de324ad1608)からの続きですー。
今回はクラスについて説明するよ！


# クラスの定義

まずは基本的な記述方法から見比べてみましょうー。
それほどガッツリと違いは無いので、すんなり読めると思います。
ですが、相違点を述べると結構あるんですよ。。

PHPのコード

```php
<?php

class Hoge {
    static private $defaultValue = 'hogehoge';
    private $value = null;

    public function __construct($value=null) {
        if ($value) {
            $this->value = $value;  
        } else {
            $this->value = self::$defaultValue;
        }
    }

    public function getValue() {
        return $this->value;
    }
}

$hoge = new Hoge();
echo $hoge->getValue();
```

Pythonのコード

```py
# coding=utf8

class Hoge(object):
    default_value = 'hogehoge'

    def __init__(self, value=None):
        if value:
            self.value = value
        else:
            self.value = self.default_value

    def get_value(self):
        return self.value

hoge = Hoge()
print(hoge.get_value())
```

## 書き方

クラスの定義はPHPと同じく`class`を用いて行います。
`if文`や`関数`と同じく、スコープの表現を`{}`ではなく`インデント`で表しています。
ここでもクラス定義の最後に`: (コロン)`をお忘れなく。

## objectクラスを継承すること！

プレーンなクラスを作る場合は必ず`objectクラス`を継承してくださいな。
継承しなくても作れるのですが、継承した方が何かと利点も多いので。
詳しく知りたい方は[コチラ](http://docs.python.jp/2.5/ref/node33.html)を参照して下さいな。

## Pythonのクラスにはアクセス修飾子はありません！

ソースを見比べて違いが判りやすい所の1つですね。
Pythonにはなんと`public`等の`アクセス修飾子`がなく、基本的には全て`public`扱いです。
一応、インスタンス変数やメソッドの名前の前に`__`をつけるとアクセス出来なくなりますよ。


## コンストラクタ

説明するまでもないと思いますが、`コンストラクタメソッドの名前`が違います。
PHPは`__construct`で、Pythonでは`__init__`ですね。

## メソッドの引数のselfって何よ。。

**「Pythonきもい！！！」** と言われる部分の一つです。。
この`self`ってのは`自身への参照（自分のインスタンス）`です。
何でそんなことすんのかってのは説明が面倒すぎるので各自ググって下さい。。

ここで重要なのは **メソッドの第一引数には必ず自身への参照が渡される** という事です。


## インスタンス変数とクラス変数の定義に気をつけて！

PHPの場合は`static修飾子`を用いて定義を分けていますが、Pythonの場合は`インスタンス変数`の定義は必ず`__init__`等の`メソッド内`で行って下さい。
`メソッド外`で定義された変数に関しては、全て`クラス変数`になります。
下記サンプルを実行すると、`Hoge.hoge`は出力されますが`Hoge.piyo`はエラーになるのが確認出来ると思います。

```py
# coding=utf8

class Hoge(object):
    hoge = 'hoge'  # クラス変数

    def __init__(self):
        self.piyo = 'piyo'  # インスタンス変数

print(Hoge.hoge)

# インスタンス変数にはインスタンス化してないのでアクセス出来ない
print(Hoge.piyo)
```

結構見落としがち（忘れがち）なのでご注意を。。

## インスタンス変数・メソッドへの参照

これも一目瞭然ですが、PHPの場合は`$this->value`で、Pythonの場合は`self.value`になります。
`アロー演算子`と`ドット演算子`の違いもあるので、気をつけて下さいねー。

`クラス変数`や`staticメソッド`に関してですが、PHPの場合は`sefl::$hoge`の様に書きますが、Pythonはインスタンス変数と同様に`self.hoge`でアクセス出来ます。


# クラスの継承

クラスの継承について説明しますよ。
いつもどおりまずはサンプルコードから。

PHPのコード

```php
<?php

class BaseClass {
    public function __construct($value) {
        $this->value = $value;
    }

    public function getValue() {
        return$this->value;
    }
}

class SubClass extends BaseClass {
    public function __construct($value) {
        $value = $value * 2;
        parent::__construct($value);
    }
}

$hoge = new SubClass(10);
echo $hoge->getValue();
```

Pythonのコード

```py
# coding=utf8

class BaseClass(object):
    def __init__(self, value):
        self.value = value

    def get_value(self):
        return self.value

class SubClass(BaseClass):
    def __init__(self, value):
        value = value * 2
        super(SubClass, self).__init__(value)

hoge = SubClass(10)
print(hoge.get_value())
```

## 継承の記述

クラスの定義の説明でもう既にやってますが、一応改めて説明しますねー。
Pythonでクラスを継承する場合は`クラス名`の後の`()`内に継承したいクラス名を記述するだけです。

```py
class SubClass(BaseClass):
```

## 親クラスのメソッドを呼ぶ

Pythonでは親クラスへアクセスする場合は`super関数`を使用します。
サンプルではコンストラクタ内で親クラスのメソッド（コンストラクタ）を呼んでいますが、通常のメソッドでも同じ方法で呼び出せます。

```py
super(SubClass, self).__init__(value)
```

分解すると以下の様な感じ。

```py
super(自身のクラス, 自身のインスタンス).呼びたい関数(引数)
```


# クラスの多重継承

なんとPythonではクラスの多重継承をサポートしています！
何かと便利な多重継承ですが、複雑になりがちなので注意して使って下さいね。

## 多重継承の記述方法

通常の継承の記述と同じです。
継承したいクラスを`()`内に記述するのですが、複数の場合は`, (カンマ)`で区切るだけ。

```py
class SubClass(HogeClass, PiyoClass):
```

## コンストラクタが呼び出される順番

**ここらへんややこしいので注意です！**
まずはサンプルコード。

```py
# coding=utf8

class A(object):
    def __init__(self):
        super(A, self).__init__()
        print('A')

class B(object):
    def __init__(self):
        super(B, self).__init__()
        print('B')

class C(A, B):
    def __init__(self):
        super(C, self).__init__()
        print('C')

instance = C()
```

`Aクラス`と`Bクラス`の2つを多重継承した`Cクラス`があります。
これを実行すると以下の様な結果になると思います。

```
B
A
C
```

結果を見ると`B -> A -> C`の順番で呼び出されている事が分かりますね。

### 何故、親クラスにsuper関数が書いてあるのか

先ほど`super関数`は親クラスにアクセスする為のものだよーなんて説明をしましたが、厳密に言うと`親または兄弟クラスにアクセス`する為の物なのです。
`Cクラス`の親クラスである`Aクラス`と`Bクラス`は兄弟の関係になるので、`super関数`が必要になるのです。

多分この説明だとまだピンとこないと思うので、次の説明を見て下さい！

### 何故、 B -> A -> C の順番になるのか

`Cクラス`の定義は`class C(A, B):`という風に`Aクラス`が先に宣言されています。
この場合`Cクラス`の直近の親は`Aクラス`という扱いになります。
つまり、`Cクラス`内の`super()`は`Aクラス`を指すことになるのです。

次に`Aクラス`を見てみると、兄弟の関係に`Bクラス`が居ます。
`super関数`は兄弟クラスにアクセスする為のものでもあるので、`Aクラス`内の`super()`は`Bクラス`を指すことになります。

残るは`Bクラス`ですが、`Bクラス`に親は居ません。
兄弟の関係として`Aクラス`が居ますが、Pythonはお利口なので`一度辿った関係は無視`してくれます。
なので`Bクラス`の`super()`が指し示すものは何もありません。

結果として、`B -> A -> C`という順番を辿ることになりました。
ちょっとややこしいけど、理解できたかな？


# Mixinクラスってやつ

PHPで言う慣れば`trait (トレイト)`に近い物かな？
**「また新しいの出てきたよ。。」** と思った方はご安心下さい。
これは只の`多重継承`のお話です。

まずはサンプル。

```py
# coding=utf8

class Mixin(object):
    def say(self):
        print('Hoge!!!!!')

class Human(Mixin, object):
    pass  # pass は「なにもしないよ」って意味。

class Cat(Mixin, object):
    pass

human = Human()
human.say()

cat = Cat()
cat.say()
```

`Humanクラス`と`Catクラス`がそれぞれ`objectクラスとMixinクラス`を多重継承しています。
もう本当に只の`多重継承`なんですが、何故違うタイトルまで付けてもう1度同じ話をするかというと、 **複数のクラスに簡単に機能を追加出来るから** なのです。
PHPの`trait`も複数のクラスに簡単に機能を付け加える為の機構でしたね。
同じような事がPythonだと`多重継承`を用いて表現する事が出来るのです。

Pythonにおける`多重継承`の使われ方は`Mixinクラス`が殆どです。
[Django](https://www.djangoproject.com)とかで使いまくると思うので、ぜひ覚えて下さい！

ちなみに、この例だと`Mixinクラス`は`objectクラス`のサブクラスなので、`Humanクラス`も`Catクラス`も以下の定義で大丈夫です。

```py
class Human(Mixin):
    pass  # pass は「なにもしないよ」って意味。

class Cat(Mixin):
    pass
```

ただの継承の話になっちゃいました。。


# まとめ

今回はクラスの作り方と継承について紹介してみました。
できる事が多い分複雑になってる感じはしますが、使いこなせると凄く便利だし楽しいです！

次は何やろうかなー未定です。。