Dive into Python 3のchapter 7を読んでみたのだが、Classes & Iteratorsなんて章の名前を付けている割に、そんなにクラスについて詳しく書いていない。具体的な継承の話なんか、まるで無いし。そこでググってみたところ、こちらの公式チュートリアルが良さそうなので、ざっと読んでみた。
多くの人が真っ先に面食らうのは、Rubyを含む多くのオブジェクト指向な言語ではimplicitに渡されるのが当たり前のselfやらthisやらが、Pythonのメソッド定義ではexplicitに第1引数として、インスタンス自身が渡される点だろう。この第1引数はselfという名前を使うことを推奨されているようだけれど、selfは単なる仮引数の名前であって予約語でも何でも無い。
そしてメソッド定義の中でさえ、インスタンス変数にはselfを介さないとアクセスできない。言い換えると、インスタンス変数はスコープに入らないのだ。Rubyだと
def methodのようにアクセスできるところが、Pythonだと
@member1 = 100
print(@member2)
end
def method(self):のようにせねばならない。
self.member1 = 100
print(self.member2)
地味に嫌らしいと思うのが、Pythonではクラスのインスタンスを介してクラス変数にアクセスできる点。Pythonだと
class Foo:こんなことが出来てしまう。Rubyでクラス定数を参照しようと思ったら
x = 100
foo = Foo()
print(foo.x)
class Fooのように、インスタンスではなくクラス名の修飾が必要。
X = 100
end
print(Foo::X)
print(Foo.new.X) # error
他にも、public, protected, privateと言ったアクセス制限の機能がPythonにはない。_memberみたいに'_'を付けたメンバはprivate扱いしてね、みたいなコーディングルールで凌いでいるようだ。まあLLならそれくらいの緩さでも許されるだろう。
問題は継承。ずばり、Pythonは多重継承が出来る。これだけでもう、Rubyで言うところのmix-inだの、Javaで言うところのinterfaceだの、そんな細かい話は吹っ飛んでしまう。属性の検索が基本的に深さ優先探索で行われるというのも要注意だろう。A, Bの順に多重継承した場合、BよりAの曾祖父の方が先に探索されるのだ。実装を考えればそりゃそうなんだろうけど、普段から多重継承が制限された世界で過ごしていると違和感を禁じ得ない。
0 件のコメント:
コメントを投稿