こんにちは!ビーバー@ゲーム業界歴約20年python勉強中 です。
maya python初心者の方のために、カンタン・わかりやすい解説サイトを作っています。
maya の pythonでGUIを作りたい、、、、んだけど、
「クラス」ってなんなのかわからない。。
この記事は、そんな方のお悩みにこたえる、クラスの解説です。
今回は3回目!「継承」について説明していきます。
動物の例で解説し、そのあとmayaでウィンドウを作って実践してみます。
継承を理解すれば、外部ライブラリを使ったGUIを作れるようになりますよ。

外部ライブラリって、、、?

例えば、pySideだよ。
pySideの機能を、継承してUI作成すると、がぜん効率があがるんだ!

わあ!pySide!使ってみたかったんだよ~
それではいってみましょう~☆

※当サイトで紹介する商品は、アフィリエイトプログラムを利用しています。
継承ってなあに
あるクラスの特徴や機能を、別のクラスに引き継がせることを、継承と言います。
継承を使うと、クラス間に親子のような関係を作ることができます。
機能を引き継がせる元となるクラスを、「親クラス」といい、
引き継ぐ方のクラスを「子クラス」と言います。

親クラスは、スーパークラス や 基底クラス って呼ばれることもあるよ!
子クラスは、サブクラス や 派生クラス とも呼ばれるね。
例をあげて説明しましょう。
例えば、「動物クラス」が、「なく」と「たべる」というメソッドを持っていたとします。
「犬クラス」と「ネコクラス」は、動物クラスを継承することで、
動物クラスの持つメソッドを利用することができます。
また、子クラスは独自のメソッドを追加することもできます。
ネコの「ねる」「あそぶ」が独自のメソッドです。


親クラスの力をかりながら、子クラスで新しいことができるんだね!
あるクラスの特徴や機能を、別のクラスに引き継がせることを、継承と言います。
親クラスと子クラスを作ろう
それでは、この図の例をスクリプトにしてみましょう!

◆python2系の書き方はこちら↓
class Animal(object):
def __init__(self, name):
self.name = name
def make_sound(self):
print self.name + "はなきます。"
def eat(self):
print self.name + "はたべます。"
class Dog(Animal):
def __init__(self, name):
super(Dog, self).__init__(name)
class Cat(Animal):
def __init__(self, name):
super(Cat, self).__init__(name)
self.name = name + "ちゃん"
def sleep(self):
print self.name + "は、ねます。"
def play(self):
print self.name + "は、あそびます。"
dog = Dog("ポチ")
dog.make_sound()
dog.eat()
cat = Cat("タマ")
cat.make_sound()
cat.eat()
cat.sleep()
cat.play()
class Animal:
def __init__(self, name):
self.name = name
def make_sound(self):
print(f"{self.name}は鳴きます。")
def eat(self):
print(f"{self.name}は食べます。")
class Dog(Animal):
def __init__(self, name):
super().__init__(name)
class Cat(Animal):
def __init__(self, name):
super().__init__(name)
self.name = name + "ちゃん"
def sleep(self):
print(f"{self.name}は寝ます。")
def play(self):
print(f"{self.name}は遊びます。")
dog = Dog("ポチ")
dog.make_sound()
dog.eat()
cat = Cat("タマ")
cat.make_sound()
cat.eat()
cat.sleep()
cat.play()
親クラスをつくる
まず、親クラス「Animal」を作ります。
このクラスでは、動物が共通して持つ「なく」と「たべる」のメソッドを定義します。
※クラスの書き方を知りたい方はこちら
class Animal(object):
def __init__(self, name):
self.name = name
def make_sound(self):
print self.name + "はなきます。"
def eat(self):
print self.name + "はたべます。"

class Animal(object):
クラス名の後ろについてる(object)ってなあに?

python2系の書き方だよ。
python2では、親クラスを作る場合 引数に(object)を入れるのが推奨されているんだ。
3系では必要ないよ!
◆python2系
class クラス名(object):
◆python3系
class クラス名:
子クラスをつくる
次に、親クラス「Animal」の特徴を受け継ぐ、子クラス「Dog」を作りましょう。
親を継承した子クラスを作るには、
class 子クラス名(親クラス名):
と、書きます。
class Dog(Animal):
def __init__(self, name):
super(Dog, self).__init__(name)

class Dog(Animal):
で、Animalクラスを継承するんだね。

そうだよ、インスタンスをつくって、
Dogクラスが親のメソッドを引き継いでいることを確認してみよう。

Dogクラスに引数「ポチ」を与え、インスタンス「dog」を作成、
make_soundメソッドと eatメソッドを実行します。

実行結果です。「ポチはなきます。」「ポチはたべます。」と出力されました。
Dogクラスには、メソッドの定義はないので
Animalクラスのメソッドを継承しているのがわかります。
このように、親を継承した子クラスは、親クラスのメソッドをすべて使うことができます。
◆python2&3共通
class 子クラス名(親クラス名):
super()とは?

おお~~!便利だねえ~~。そしたらさ、スクリプトの3行目の、
super(Dog, self).__init__(name)
っていう部分はなあに?
class Dog(Animal):
def __init__(self, name):
super(Dog, self).__init__(name)

ここでは、親クラスのコンストラクタを呼び出しているんだよ。
※コンストラクタってなんだったっけ?という方はこちら
super関数は、親クラスを呼び出す関数です。
super().メソッド名()で、親クラスのメソッドを呼び出すことができます。
super関数は、python2と3で書き方が異なります。
◆python2
super(子クラス名, self).メソッド名()
◆python3
super().メソッド名()

python3では、super関数に引数がいらなくなったんだね!
スクリプトに戻って、
Dogクラスのコンストラクタの中身は、super関数の1行のみになっています。
class Dog(Animal):
def __init__(self, name):
super(Dog, self).__init__(name)
super関数で __init__メソッドを呼んでいるので、
この処理は 親クラスの__init__、つまり親のコンストラクタの処理をそのまま継承する、
という意味になります。
独自のメソッドをもつ子クラスをつくる
親クラス「Animal」の特徴を受け継ぎつつ、
独自のメソッドを追加した猫のクラス「Cat」を作ってみましょう。
メソッド追加は、通常の関数の宣言とおなじく def~で書きます。
このとき、親クラスにないメソッド名を使うとメソッドを追加することができます。
class Cat(Animal):
def __init__(self, name):
super(Cat, self).__init__(name)
self.name = name + "ちゃん"
def sleep(self):
print self.name + "は、ねます。"
def play(self):
print self.name + "は、あそびます。"
sleepメソッドと、playメソッドを追加しました。
Catのインスタンスを作って、動作を確認してみましょう。
cat = Cat("タマ")
cat.make_sound()
cat.eat()
cat.sleep()
cat.play()
インスタンス「cat」から、メソッドmake_soundと eatメソッドを呼び出します。
また、Catクラス独自に追加した、sleepとplayメソッドも実行してみます。
実行結果

sleepとplayメソッドが実行されているのを確認できました!
class 子クラス名(親クラス名):
□□□□def メソッド名(self):
※メソッド追加は、親クラスにないメソッド名を使う

おーっ!追加メソッドがちゃんと動いた!
…ってあれ?出力が、タマ「ちゃん」ってなってるね?

良く気づいたね!Catクラスのコンストラクタに、
「ちゃん」をつける処理を追加したんだ。
Catクラスのコンストラクタ(__init__のなか)を見てみましょう。
class Cat(Animal):
def __init__(self, name):
super(Cat, self).__init__(name)
self.name = name + "ちゃん"
4行目に、 self.name = name + “ちゃん” という処理が追加されていますね。
変数nameで受けた文字列に、”ちゃん”をつけたし、インスタンス変数として使えるように
self.name に代入しなおしています。
※selfって何だったっけ?という方はこちら

コンストラクタにも、子クラス独自の処理を追加することができるんだね!
親クラスのメソッドをオーバーライドする
オーバーライドとは、メソッドの上書きのことです。
親クラスのメソッドを、子クラスで上書きして使うこともできます。
Catクラスの make_soundメソッドを、書きかえてみます。
class Cat(Animal):
def __init__(self, name):
super(Cat, self).__init__(name)
self.name = name + "ちゃん"
def make_sound(self):
print self.name + "は、にゃおーんとなくよ!"
出力結果


おお、タマちゃんのなき方がにゃおーんになった!
親クラスと同じメソッド名で、super関数を使わず処理を書くと、
親クラスのメソッドを上書きすることができます。
class 子クラス名(親クラス名):
□□□□def 親クラスのメソッド名(self):
親クラスと同じメソッド名で新たな処理を書くと、メソッドを上書きすることができる
※super関数を使わない
このように、継承を使うと親クラスの特徴を子クラスへかんたんに引き継ぐことができます。

親クラスと子クラスで機能を振り分けると、何度も同じスクリプトを書かなくてもよくなるよ。
整理されて読みやすくなるし、効率的に書けるよね!

継承を使ってウィンドウを作ってみよう

それでは、継承をつかってMayaのウィンドウ作ってみましょう!
親ウィンドウクラス「BaseWindow」を作って、
その特徴を子ウィンドウ「CustomWindow」に継承させてみます。
親クラスの作成
まず、BaseWindowクラスを作ります。
BaseWindowクラスでは、ウィンドウの作成・表示と、タイトルづけだけを行います。
import maya.cmds as cmds
class BaseWindow(object):
def __init__(self, title):
self.title = title
def create_window(self):
window = cmds.window(title=self.title, widthHeight=(300, 200))
cmds.showWindow(window)

タイトル名を引数でとるようにしているね。
BaseWindowのインスタンスを作って、create_windowメソッドを呼び出してみましょう。
引数で受け取った「ベース」というタイトル名がついた、素のウィンドウができます。

子クラスの作成
次に、親クラスを継承した、子クラス「CustomWindow」を作ります。
CustomWindowクラスでは、
「ウィンドウにレイアウトを設定して、ボタンを表示する機能」を追加します。

素のウィンドウを作るところは親クラスにまとめて、
子クラスでは、ウィンドウの中身を作る作戦だね!
class CustomWindow(BaseWindow):
def __init__(self, title):
super(CustomWindow, self).__init__(title)
def create_window(self):
super(CustomWindow, self).create_window()
cmds.columnLayout()
cmds.button(label='ボタン')
create_windowメソッドは、親クラスの同名メソッドにレイアウトとボタンの処理を追加しています。
CustomWindowのインスタンスを作って、ウィンドウを表示してみましょう。

タイトル名が「テスト」、ボタンが配置されたウィンドウができました!
このように、ウィンドウの共通部分を親クラスにまとめ、
子クラスにボタンなどの要素を入れておくと、
様々な用途のウィンドウ作成が楽にできるようになります。

ウィンドウを作るのに、毎回共通部分を書かなくてすむよね。
まとめ
今回のブログ記事では、クラスの継承について解説しました!
ポイントをまとめます。
- 継承とは、あるクラスの特徴や機能を、別のクラスに引き継がせること です。
- 機能を引き継がせる元となるクラスを、「親クラス」といい、
引き継ぐ方のクラスを「子クラス」と言います。
- 子クラスは独自のメソッドを追加したり、
親のメソッドをオーバーライド(上書き)することができます。
- 共通の機能を親クラスにまとめ、子クラスに独自の処理をまとめると、
効率的にスクリプトを作成することができます。
クラスと継承が使いこなせるようになると、より楽に&自由にGUIが作れるようになりますよ!
クラスの理解を深めて、「ちょっと凝ってるGUI」を作りましょう~☆
最後まで読んでくれてありがとうございました!

また読みに来てね~~☆
◆クラスの学習にオススメコンテンツ
体系的に学ぶのに心強いコンテンツ!使ってみてよかったものをご紹介します。
【書籍 Python3 スキルアップ教科書】
説明がシンプルで明快!リファレンスとして手元に置いておきたい一冊。
コードと出力結果が多くのっていて、理屈じゃなく実体験で機能が理解できます。
Python3の試験を実施している「Pythonエンジニア育成推進協会」が書いているのも納得☆

【paizaラーニング】
クラスの説明は15本の動画があり、それぞれ5分程度の短い動画で、
思い立った時にサクッと勉強できるのがありがたかったです。
ブラウザ上でコードを書いて学習できるので便利。無料なのもうれしいポイント!

【Udemy】
オブジェクトの成り立ちからコードの書き方まで、とても丁寧に説明されています。
1回聞いただけで概要がすっと頭に入ってきました。
Python でわかる オブジェクト指向 とはなにか?【Python オブジェクト指向 の「なぜ?」を「徹底的に」解説】

【PyQ】
Pythonに特化したオンライン学習サービス。ブラウザのみで学習できます。
コードの「写経」があるのが特徴的で、体験しながら理解ができるしくみになっています。
ライトプランなら月々3040円。いつでも開始・終了できるのも気楽で良いですね。
無料で1週間のお試しもできますよ☆

クラスやオブジェクトを理解しようとすると、突然ハードルが上がって感じますよね。
オブジェクト指向プログラミングを使いこなすには、体系的な学習が必要になります。
「付け焼刃でなく、プログラミングについてしっかりした理解をしたい」
こんな人には、腰を据えて本格的な学習ができる「Recursion」という
オンライン学習サービスをおすすめします。
Recursionで学習すると、
特定の言語にしばられない応用のきく実践的な力がつくので、
自分で問題解決をしていけるようになります。
maya pythonでGUIを作る方法をもっと知りたい方はこちら。
cmdsで作る方法・PySideの紹介・PySideのかんたんなチュートリアルをまとめています。
PySideを使うときに必要になる、「クラス」についても徹底解説!
本サイトの【まとめ】 maya python 基礎 入門!では、
10回シリーズでmaya pythonの基礎が習得できるコンテンツを発信しています。
- ちまたのスクリプトを読んで、内容を理解したい
- mayaのスクリプトリファレンスの読み方を習得したい
- 自分で簡単なツールを書きたい
- 基礎的なmayaコマンドをpythonで使えるようになりたい
など、mayaでpython基礎を身に着けたい方は、ぜひご活用ください♪
コメント