この章では親クラスの変数を子クラスで初期化する方法について説明します。 子クラスの中で親クラスの変数と子クラスの変数を子クラスの中で初期化したい場合は以下のように書きます。 子クラスのinitメソッドの引数の内、a,c,fが親クラスのインスタンス変数の初期化に使われて、残りのeが子クラスのインスタンス変数company1の初期化に使われます。
ですので、オブジェクトの引数は4つになります。 図にすると以下のようになります。 結果は次の通りです。
タグ: クラス
クラスの継承について知ろう1
この章ではクラスの継承について説明します。
親クラスの機能を引き継ぐクラスであるサブクラスを作成することを継承といいます。
親クラス(スーパークラスとも言います)とは元のクラスのことで、以下の例ではBankクラスがこれに該当します。
サブクラス(子クラスとも言います)とは親クラスの機能を引き継いだクラスです。
以下の例ではShoukenクラスがこれに該当します。
子クラスは親クラスのメソッドや変数を全て使うことができますので、子クラスでは親クラスのメソッドや変数をあえて書く必要はありません。
子クラスではゼロから親クラスにあるメソッドや変数を作らなくていいので、プログラムがすっきりします。
BankはShoukenを内包しているので継承関係が成り立つわけで、まったく関係ないクラス同士を継承させても意味はありません。
例えばCarクラスとBankクラスは全く機能が違うので、継承関係にしても意味がありません。
では例をみてみましょう。 結果は次の通りです。 クラスの継承は以下の構文で書きます。 例ではの箇所です。
以下の通り、子クラスのメソッド内では親クラスの変数を使うことが出来ますが、形式はです。 子クラスは親クラスのメソッドや変数を全て使うことができますので、以下の通り子クラスのオブジェクトから親クラスのメソッドを使うことができます。
次にオーバーライドについて説明します。
子クラスでは親クラスのメソッドと同じ名前で内容だけ違うメソッドを作成することが出来ます。
これをオーバーライドと言います。
メソッド名は変えずに、子クラス独自の内容に変えることが出来ます。
クラスについて知ろう
この章ではクラスについて説明します。
今までのプログラムでは変数と関数を扱ってきましたが、クラスという機能を使うことで多くの変数と関数を1つの機能体として働かせてデータを処理することができます。
クラスとは物を作る設計図に例えられます。
設計図は車や家や鉛筆をつくる場合に必要ですが、この設計図に当たるものがクラスです。
ではクラスについて詳細に説明します。
車や家や鉛筆の中には色々な部品が含まれていますが、それらの部品には「状態」や「ふるまい」があります。
例えば、鉛筆であれば「状態」は鉛筆の形、芯、線の濃さなどで、「ふるまい」は線を引く、削るなどの動作です。
その「状態」や「ふるまい」をクラスという設計図に書いていきます。
「状態」を変数で書き、「ふるまい」をメソッドで書くことになります。
その「状態」や「ふるまい」に指示を出すのはオブジェクトです。
例えば鉛筆の「線を消す」など具体的な指示をオブジェクトという司令塔から出します。
オブジェクトの詳細はこの後に説明します。
ではクラスの基本形から説明します。 〇クラス名は大文字で付けることが慣習になっていますが、自由に付けていただいて結構です。
〇クラスの中に変数やメソッドを書いていきます。
メソッドは関数の別名だと思ってください。 〇この引数はクラスの中で使われるデータです。
〇引数は必要な場合には記述しますが、省略もできます。
ではクラスの例を見てみましょう。 この例のクラスにはBankと言う名前が付いています。
そして、このBankクラスを使うためにはオブジェクトを作成しなくてはいけません。
クラスはただの設計図なので、これを動かすのがオブジェクトです。
それがの箇所です。
オブジェクトを作った後は、そのオブジェクト変数を使って、クラスの中の変数やメソッドにアクセスすることができるようになります。 「クラス名(引数)」という形式で引数が 書かれていますが、この引数はオブジェクトを作成した時に実行するinitメソッドに渡されます。
このinitメソッドの中で設定した変数にオブジェクトで設定したデータを入れます。 initメソッドの構文は次の通りです。 〇 initメソッドの第一引数は引数があっても無くてもselfと書いてください。
selfはオブジェクト自身を意味します。
〇注意点はinitの前後の下線は2つ連続で繋がっています。
この例では下線が1本に見えますがテキストエディタの表記のせいです。
〇 initメソッドはPythonで機能が与えられているメソッドですが、nyuukinメソッドやshukkinメソッドは自分で作成したメソッドです。
ではプログラムの説明をします。
banks=Bank(1200000)のようにオブジェクトを作成すると同時に引数である1200000がinitメソッドの引数であるaにセットされ、self.zandakaに代入されます。
initメソッドやnyuukinメソッドなどのメソッドの中の第一引数には必ずselfを設定します。
また、メソッドの中にクラス内で設定した変数がある場合はその変数にもと言う形式でselfを付けます。
この例ではの箇所です。 「self.zandaka」のようにselfに関連づけられている変数をインスタンス変数と言います。
次はメソッドにデータを入れる方法について説明します。 「オブジェクト.メソッド(引数)」と いう形式でクラスの中の以下のnyuukinメソッドを呼び出して、に15000を足す動作を行っています。 このようにオブジェクトから呼ばれるメソッドをインスタンスメソッドと言います。
次に以下の説明をします。 クラスの中のshukkinメソッドを呼び出して、zandakaからkの値である10000を引く動作を行っています。 そして最後に の箇所で、以下のshowメソッドを実行しています。 showメソッドはzandakaの値をreturnで呼び出し元に返すだけのメソッドです。
結果は以下の通りです。 先ほどの例ではzandakaという変数が初めから定義されていますが、実はこれらの変数は初めからクラスの中で定義しなくても、後からでも付け加えることができるのです。
例えば「ginkou」という変数を付け加えようとする場合にはと言う形式で付け加えることができます。
例えば以下のように書きます。 では例をみてみましょう。 このginkou変数はshowメソッドで使われているのが分かります。
次の例に進みます。
インスタンス変数は前の例のの代わりに以下のようにクラスの中に初めから設定しておくことも出来ますので次の例をみてください。 この例のようにクラスの中にインスタンス変数を初めから設定することができます。
クラスの中で変数を設定する時には変数の前にオブジェクトを付ける必要はありません。 次の箇所の説明をします。 このようにオブジェクトからクラスのインスタンス変数の値を取得することもできます。
クラスの中の変数の値を取得するにはという形式で書きます。 これまでの例ではオブジェクトは1つだけでしたが、以下のように複数のオブジェクトを作成することができます。
以下の例では複数のオブジェクトごとにzandaka変数に値を入れていますが、これらのオブジェクト間で値の共有はありません。
つまり、新しくオブジェクトを作ったら、前のオブジェクトで使われていた変数の値は使われることはありません。
クラスの継承について説明します
この章ではクラスの継承について説明します。
クラスの継承とは元々あるクラスを拡張して、新しいクラスを作成することを言います。新しいクラスを作成するのに元のクラスと変数やメソッドが重なった場合, 元のクラスの機能を使える仕組みが継承です。
つまり、新しいクラスをゼロから作成するのではなく、元のクラスの機能を借りて新しいクラスを作成する仕組みが継承です。
元のクラスを親クラス(スーパークラスとも言います)、その親クラスを受け継いだクラスを子クラス(サブクラスとも言います)と言います。 では少し長いですが例をみてみましょう。 では説明を始めていきます。
この例では親クラスのBankクラスを受け継いだShoukenクラスを作成しています。
その子クラスの中には親クラスにはない子クラス独自のメソッドや変数を書きます。
なぜなら、子クラスは親クラスのメソッドや変数を全て使うことができるので、あえて親クラスのメソッドや変数を書く必要が無いからです。
ではどこで親クラスの変数を取得しているかと言いますとです。
superとは親クラスを意味します。
子クラスの中でsuperはinitializeメソッドの中にありますが、この場合にはsuperは親クラスのinitializeメソッドを呼ぶことを意味します。
子クラスのメソッドの中でsuperを使うとそのメソッド名と同名のメソッドを親クラスから呼び出すことができます。
この例では子クラスのinitializeメソッドの中でsuperを使っているので親クラスのinitializeメソッドを呼び出すことができます。 super(name,age,money)の箇所は以下の作業をしています。
オブジェクトの引数が親クラスのinitializeメソッドの中のインスタンス変数に代入されます。 そして、initializeメソッドの引数aは@company1に代入されます。 その他にもこの例では以下のように子クラスのresultメソッドからsuperを使って、親クラスのresultメソッドを呼び出しています。 実はこのresultメソッドは親クラスにも子クラスにもありますが、このように子クラスの中で親クラスと同じ名前で中身だけが違うメソッドを作ることが出来ます。
これをオーバーライドと言います。
先ほども書きましたが、superの機能を詳しく言いますと子クラスの中のオーバーライドしているメソッドの中にsuperを記述すると親クラスの中の同名のメソッドを呼び出すことができます。
例えば上の例では子クラスのresultメソッドから親クラスのresultメソッドを呼び出しています。
では次の箇所の説明をします。 複数の箇所でを使っていますが、「+」は文字列同士を連結する機能がありますので、オブジェクトが数値の場合にはを使用して、文字列に変換してください。 結果は以下の通りです。
クラスについて知ろう
この章ではクラスについて説明します。
今までのプログラムでは変数とメソッドを扱ってきましたが、クラスと言う機能を使うことで、多くの変数とメソッドを1つの機能体として働かせてデータを処理することが出来ます。
クラスとは物を作る設計図に例えられます。設計図は車や家や鉛筆をつくる場合に必要ですが、この設計図に当たるものがクラスです。
例えば車や家や鉛筆の中には色々な部品が含まれていますが、それらの部品には「状態」や「ふるまい」があります。
鉛筆であれば「状態」は鉛筆の形、芯、線の濃さなどで、「ふるまい」は線を引く、削るなどの動作です。
その「状態」や「ふるまい」をクラスと言う設計図に書いていきます。
「状態」を変数で書き、「ふるまい」をメソッドで書くことになります。
その「状態」や「ふるまい」に指示を出すのはオブジェクトの役割です。
例えば「線を消す」など具体的な指示をオブジェクトと言う司令塔から出します。
クラスの基本構文は以下の通りです。 クラス名の初めの一文字目は大文字のアルファベットで書きます。
classとendの間に変数やメソッドなどを記述して、クラスの中身を作ります。
クラスはただの設計図なので、このクラスに指示を出す必要がありますが、それがオブジェクトです。 〇引数は省略できます。
〇このオブジェクトはインスタンスとも呼ばれています。
ではクラスの例を見てみましょう。 クラスの中に@ マークの付いている変数がありますが、これはインスタンス変数と呼ばれていまして、クラスの中で使われます。 =>オブジェクトの基本構文はと、説明しましたが、このオブジェクトを作成する過程でクラスの中のinitializeメソッドを自動的に呼び出してくれます。nyuukinメソッドやshukkinメソッドは自身で作ったメソッドですが、このinitializeメソッドはRubyであらかじめ定義されているメソッドです。
そしてこのの中の引数100000がinitializeメソッドの引数(この例ではc)に入ります。
他の言語ではコンストラクタと呼ばれる機能です。
このようにinitializeメソッドを使ってインスタンス変数に値を設定することが出来ます。
また以下の通り、初めからインスタンス変数に値を設定することもできます。
その場合にはのように引数を省略できます。 次に以下の箇所の説明をします。 =>クラス内のメソッドにデータを渡すにはという形式で書きます。
そうするとクラス内のメソッドが実行されます。
最後にshowメソッドを出力するとnyuukinメソッドやshukkinメソッドで計算された結果が入っている@zandakaが返されますので、これをprintで出力しています。
結果は「91000」です。
次の例はinitializeメソッドの引数にデフォルト値を設定する例です。 初期値を設定するときには以下のようにとデフォルト値を設定してください。
メソッドの章で説明した通り、メソッドにはあらかじめ値を設定することができます。 このようにメソッドに引数を設定した時にはオブジェクトの引数をカラにしても、そのメソッドの引数の設定値が使用されます。
先ほども説明しましたが、もう一度クラスの中のメソッドを呼び出す方法について説明します。
この例ではクラスの中で3つのメソッドを定義しています。 これらのメソッドを使用するためにはという構文で書きます(initializeメソッドだけはオブジェクトを作成過程で自動的に呼び出されるので、明示的にこの構文を使う必要はありません)。
この構文でメソッドにデータを入れていきます。この例では以下のように書いています。 引数が無い場合にはshowメソッドのように省略することができます。 これらのメソッドはオブジェクトからアクセスするのでインスタンスメソッドと言います。
今までのトップレベルのメソッドはのようにメソッド名だけでメソッドを呼び出していましたが、オブジェクトから呼び出す場合はで書くことを覚えておいてください。
次にインスタンス変数について説明します。
インスタンス変数はインスタンスメソッドからのみ参照できますので、メソッドを通してインスタンス変数の値を取得します。
ですので、この例ではすべてメソッドの中でインスタンス変数の値を足したり、引いたりしています。
では次の説明に進みます。
オブジェクトは1つだけではなく、次のように変数を変えていただくと何個でも作ることが出来ます。
例えばこの例ではbooksとbooks2の2つを作成しています。 オブジェクトをたくさん作成してもインスタンス変数はオブジェクトごとに値が設定されますので、booksの@zandakaとbooks2の@zandakaの間には関係性はありません。
結果は以下の通りです。
では次の例を見てみましょう。 では説明をしていきます。
initializeメソッドでインスタンス変数に値を設定することもできますし、setメソッド(メソッド名はsetを付けなくても構いません)を使っても値を設定することができます。
この例ではsetメソッドで設定した値でinitializeメソッドで設定した値を上書きしていますが、initializeメソッドで設定したデータよりsetメソッドで設定したデータの方が優先されます。
setメソッドだけで値を設定したい場合にはinitializeメソッドは書かなくても結構です。
ではsetメソッドについて説明します。
インスタンス変数に値をセットするためにはinitializeメソッドやsetメソッドを通常使用します。 =>「set..」というのはインスタンス変数の値を設定する時に使います。
特に「set..」で書かなくてはならないという決まりがあるわけではありませんが、解りやすいので慣習になっています。
通常はインスタンス変数ごとにsetメソッドを書きます。
次はgetメソッドについて説明します。 =>「get..」と言うのは値を呼び出し元に返す時に使います。
特に「get..」で書かなくてはならないと言う決まりがあるわけではありませんが、解りやすいので慣習になっています。
通常はインスタンス変数ごとにgetメソッドを書きます。
getメソッドは値を返すために作られるメソッドです。
結果は以下の通りです。 しかし、インスタンス変数の数だけ、このようなメソッドを書くのは面倒に思いませんか?
そこでRubyにはそれを簡潔にする機能が備わっています。
次の例で説明します。 では説明を始めます。
と、書くことで例えば本来ならばsetNameメソッドとgetNameメソッドを2つ書かなくてはいけませんでしたが、と書くだけでこれらの2つのメソッドと同じことを行わせることが出来ます。
このの中の変数に値を設定するにはという構文で入れていきます。
この例では以下のように入れています。 インスタンス変数の値を出力するにはという構文で記述します。
この例では以下の箇所です。 では次の例に進みます。 では説明を始めます。 「attr_writer :変数名」は以下のようなsetメソッドと同じ役割があります。 「attr_reader :変数名」は以下のようなgetメソッドと同じ役割があります。 使い方はと同じです。
クラスの継承について知ろう
この章ではクラスの継承について説明します。
クラスの継承とは親クラス(元のクラス)の他に、もう1つの関連したクラスを作ろうとした時に、親クラスのフィールド変数やメソッドを引き継ぐことを言います。
もう1つの関連したクラスのことを子クラスもしくはサブクラスと言います。
親クラスと同じフィールド変数やメソッドを子クラスで定義しなくてはいけない時、同じフィールド変数やメソッドを子クラスで再度記述する必要はありません。
また、子クラスには独自のフィールド変数やメソッドも追加することもできます。
では例を見てみましょう。Banksystemクラスが親クラスで、Securitiesクラスが子クラスになります。
SecuritiesクラスはBanksystemクラスを継承しているので、Banksystemクラスのフィールド変数やメソッドを使用することが出来ます。子クラスの中で親クラスのフィールド変数を使うことができると言いましたが、それが以下の箇所です。他にもstockbuyメソッドやstocksellメソッドの中でも使われています。また、子クラス独自のフィールド変数やメソッドを書くことができると言いましたが、それがcompany変数やstockbuyメソッドやstocksellメソッドやresultメソッドです。
改めて親クラスのメソッドやフィールドを子クラスで書く必要はありませんが、この例では1つだけ親クラスと共通のメソッドを書いています。それはresultメソッドです。このように子クラスと親クラスで名前が同じで、内容だけが違うメソッドを作ることが出来ます。
つまり、メソッド名は変えずに、子クラス独自の内容に変えることが出来ます。
これをオーバーライドと言います。次にprivate とprotectedについて説明します。
親クラスでprivateが付いているフィールド変数やメソッドは子クラスからはアクセスすることはできません。
例の親クラスのフィールド変数を以下のようにprivateに書き換えると子クラスのメソッドから使用することは出来なくなります。ですので、この例では以下のようにprotectedを付けて、子クラスでも使えるようにしています。
protectedは子クラスから親クラスにアクセスできることを意味します。結果は以下の通りです。次は子クラスから親クラスのコンストラクタを呼び出す例です。結果は以下の通りです。では子クラスから親クラスのコンストラクタを呼び出す方法について説明します。
Mainメソッド内で子クラスのオブジェクトを作成し、ここで親クラスや子クラスのフィールド変数にデータを入れています。上のように子クラスであるUsedクラスのオブジェクトが作られた時にはまず初めに自動的に親クラスの引数の無いコンストラクタが呼ばれます。つまり親クラスに引数のあるコンストラクタだけで、引数の無いコンストラクタが無い場合はエラーになります。
親クラスの引数の無いコンストラクタが呼ばれた後に子クラスのコンストラクタが呼ばれることになります。
この例の場合にはコンストラクタの中でさらにsetfieldメソッドを呼び出して値のチェックをしています。
このような書き方も出来ますので覚えておいてください。自動的に親クラスの引数の無いコンストラクタが呼ばれると書きましたが、では親クラスに引数の無いコンストラクタが無い場合エラーになるのだとしたら、どう対処したらいいでしょうか?
方法は2つありますが、1つ目はこの例のように親クラスに引数の無いコンストラクタを作っておくことです。
2つ目は子クラスのコンストラクタの中で親クラスの引数のあるコンストラクタを呼び出す方法です。子クラスコンストラクタの中の引数には親クラスと子クラスのコンストラクタの引数を型も含めて記述します。
baseの中にある引数は親クラスの引数のあるコンストラクタに渡しますが、ここの引数には型名を入れる必要はありません。
では先ほどの例を2つ目の方法で書き換えてみましょう。オブジェクトを作成した時にコンストラクタが実行されますが、n, a, bが親クラスのコンストラクタの引数に入ります。
そしてs, fが子クラスのsetfieldメソッドの引数に代入されることになります。
図にすると以下のようにデータが入ります。結果は以下の通りです。
クラスについて知ろう
この章ではクラスについて説明します。
今までのプログラムでは変数とメソッドを扱ってきましたが、クラスと言う機能を使うことで、多くの変数とメソッドを1つの機能体として働かせてデータを処理することが出来ます。
クラスとは何かしらの物を作る設計図に例えられます。
設計図は車や家や鉛筆をつくる場合に必要ですが、この設計図に当たるものがクラスです。
車や家や鉛筆の中には色々な部品が含まれていますが、それらの部品には「状態」や「ふるまい」があります。
例えば、鉛筆であれば、「状態」は鉛筆の形、芯、線の濃さなどで、「ふるまい」は線を引く、削るなどの動作です。
その「状態」や「ふるまい」をクラスと言う設計図に書いていきます。
「状態」を「変数」で書き、「ふるまい」をメソッドで書くことになります。
どのような「状態」や「ふるまい」を作りたいかはオブジェクトの役割です。
例えば「線を引く」「線を消す」など具体的な指示をオブジェクトと言う司令塔から出します。
クラスの構文は以下の通りです。 クラスの中に変数やメソッドを書いていきます。
クラスの中の変数をフィールド変数と言います。
次にアクセスレベルについて説明します。
アクセスレベルとは変数やメソッドで使われますが、それらの変数やメソッドに対して、どこからアクセスできて、どこからアクセスできないかを決める修飾子です。
次はオブジェクトについて説明します。
オブジェクトはnew演算子を使って作成します。
オブジェクトとはクラスの中の「状態」を表す変数や「ふるまい」を表すメソッドに指示を出す役割があります。
例えば「線を消す」など具体的な指示をオブジェクトと言う司令塔から出します。 オブジェクトを作る過程をインスタンス化と言います。
ではクラスで作ったプログラムの例を見てみましょう。 このプログラムは銀行でのお金の入金や出金のシステムを簡潔に作っています。2つのクラスがありますが、1つはMainメソッドのあるProgramクラスで、もう1つはGinkouクラスです。
初めにプログラムが実行されるMainメソッドのあるProgramクラスが司令塔になって、他のクラスに指示を出していくことになります。 クラスのフィールド変数には以下の構文でデータを入れます。 クラスのメソッドを実行するためには以下の構文で行います。 その結果、それぞれ以下のメソッドが実行されます。 これらのメソッドはインスタンス化(オブジェクトが作られてから)されてから実行されるのでインスタンスメソッドと呼ばれています。
それぞれのフィールド変数にデータが入ったところで、最後にresultメソッドで出力しています。
結果は以下の通りです。 この例ではProgramクラスを消して、Ginkouクラスにまとめています。
次はアクセスレベルのprivateについて説明します。
これまでのクラスのフィールド変数はpublicにしていますが、これは本来はよろしくありません。
クラスの外側から直接値を入れることが出来てしまうからです。
そこで、フィールド変数はprivateにして、メソッドからこれらのフィールド変数に値を入れる方が最良です。
そして、メソッドはpublicにするのが基本です。
例を見てみましょう。 この例ではすべてのフィールド変数にthisを付けていますが、前の例のように省略が出来ます。
クラスの継承について知ろう
次はクラスの継承について説明します。
「クラスの継承」とは親クラス(元のクラス)の他に「もう1つの関連したクラス」を作る時に親クラスのデータメンバやメンバ関数を引き継ぐことを言います。
「もう1つの関連したクラス」のことを子クラスもしくはサブクラスといいます。
親クラスと同じデータメンバやメンバ関数を子クラスで定義しなくてはいけない時、親クラスと同じデータメンバやメンバ関数を子クラスで再度記述する必要がなくなります。
つまり、親クラスと同じ機能を持つデータメンバやメンバ関数を子クラスで使う時に、改めて同じデータメンバやメンバ関数を子クラスで書くのは無駄ですので、そのような時にクラスの継承を使います。
また、子クラスには子クラス独自のデータメンバやメンバ関数も追加することもできます。
注意してほしいことは全く違うクラス同士を継承しても意味が無いと言うことです。
例えば銀行クラスと自動車クラスは全く違うクラスなので、継承関係にしても意味ありません(意味があればいいですが)。
継承関係が正しいかどうか悩む場合には「子クラスは親クラスの子供である」という文の「子クラス」「親クラス」に自身で作ったクラス名を当てはめてみて、違和感がないようでしたらそれは正しい継承関係です。
「銀行クラスは自動車クラスの子供である」と聞いてもおかしいと思いませんか?
違和感があるようでしたらそれは意味が無い継承です。
では継承の例を見てみましょう。 では説明に入ります。
クラスの継承の基本構文は以下の通り書きます。 この例では以下の箇所が継承クラスの箇所です。
ここで継承クラスのポイントを説明します。
[ポイント1]
子クラスでは親クラスのデータメンバやメンバ関数を受け継いでいるので、親クラスのメンバを使うことが出来ます。
この例では子クラスのオブジェクトから親クラスのメンバ関数に以下のようにアクセスしています(親クラスのメンバをすべて使用する必要はありません)。 子クラスではdeposit関数を定義していないにも関わらずdeposit関数を使うことができるのが継承の意味です。
つまり、子クラスではprivate指定以外の親クラスのデータメンバやメンバ関数をすべて使うことが出来ます。
[ポイント2]
子クラスの引数のないオブジェクトを作成した時には先に親クラスの「引数の無いコンストラクタ」が実行されてから小クラスのコンストラクタが実行されますので初めに実行されるには以下の親クラスのコンストラクタです。
この記述で親クラスのデータメンバにデータを入れているので、子クラスで親クラスのデータメンバを使うことが出来ます。
親クラスの引数の無いコンストラクタが実行された後に、子クラスの「引数の無いコンストラクタ」が実行されます。 [ポイント3] 親クラスの定義の中に上の記述がありますが, 親クラスのメンバがprotectedで指定されている場合は子クラスの中で、そのデータメンバやメンバ関数にアクセスできます。
以下のように親クラスでprivate指定してしまうと子クラスからはアクセスすることが出来なくなります。 [ポイント4]
次は親クラスと小クラスで同じ名前のメンバ関数を定義した場合、どのような動きになるか見てみましょう。
この例では以下の部分で親クラスと子クラスで同じ関数名が使われています。 親クラスと子クラスでは関数名も引数の数や型も同じ関数を作ることが出来ます(メソッドの中身はそれぞれのクラスの内容に合わせます)。
このことをオーバーライドと言います。
この例の場合、子クラスのオブジェクトからのようにgetPoint関数を呼び出していますが、子クラスで定義された関数のほうが優先して呼び出されることになります。
この例の結果は以下の通りです。
オブジェクト指向プログラミングについて
この章ではオブジェクト指向プログラミングについて説明します。
オブジェクト指向プログラミングはC言語にはない機能であり、C++で新たに取り入れられた機能です。
オブジェクト指向型プログラミングは構造体に似た機能を持っています。
オブジェクト指向型プログラミングを使用すると変数と関数を1つにまとめることが出来ますが、この作業は「クラス」を使って行います。
つまり、「クラス」を使うことで、多くの変数と関数を1つの機能体として働かせてデータを処理することが出来ます。
クラスとは何かしらの物を作る「設計図」に例えられます。
設計図は車や家や鉛筆などをつくる場合に必要ですが、この設計図に当たるものがクラスです。
車や家や鉛筆の中には色々な部品が含まれていますが、それらの部品には「状態」や「ふるまい」があります。
例えば、鉛筆であれば、「状態」は鉛筆の形、芯、線の濃さなどで、「ふるまい」は線を引くなどの動作です。
その「状態」や「ふるまい」をクラスと言う設計図に書いていきます。
「状態」を変数で書き、「ふるまい」を関数で書くことになります。
どのような「状態」や「ふるまい」を作りたいかは「オブジェクト」の役割です。
例えば「線を書く」「線を消す」など具体的な指示をオブジェクトと言う司令塔から出します。
では初めにクラスの基本から説明します。
クラスの中に「状態」を変数に書き、「ふるまい」を関数に書きます。
クラスの中の変数をデータメンバ、関数をメンバ関数と呼びます。
これをクラスの宣言と言います。 クラス名が2文字で構成されている場合、それぞれの単語の先頭を大文字で書いて、その他は小文字で書くのが慣例になっています(この通り書かなくてもエラーにはなりません)。
次はオブジェクトの作成方法について説明します。
オブジェクトについては先ほど以下のように説明しました。 つまりオブジェクトから命令を出してクラスに対して仕事をさせる役割があります。 今まではint型などの変数を作っていましたが、オブジェクトは「クラス型の変数」を作ることを意味します。
このオブジェクトを作る過程をインスタンスと言います。
ではクラスとオブジェクトの関係のイメージをつかむためにもう一度説明します。
例えば新築の家をつくるとします。
ある人は家にプールを作ったり、床暖房を付けます。
そのことを実現するには設計図に「プールや床暖房」や「その機能」を付け加えないといけません。
実際には設計図であるクラスの中にプール、床暖房という変数を設定し、プールや床暖房の機能を定義するために関数内で水や床の温度を上げたり下げたりする機能を加える必要があります。
この設計図はそのままでは動きませんので、誰かの指揮のもとに動かさなくてはいけません。
その指揮者の役割がオブジェクトです。
オブジェクトは例えば冬になったらプールの水の温度を40度にするなど細かな指示をすることになります。
では実際に例を見てみましょう。 改めてクラスの定義の記述方法について説明します。 クラスはデータメンバとメンバ関数からできています。
クラスの中の変数をデータメンバ、クラスの中の関数をメンバ関数と呼ばれていることは説明しました。
アクセス指定子とはメンバに対して、どこからのアクセスを許可するのかを指定するものです。
つまり、クラスは複数作ることが出来ますので、どのクラスからアクセスすることができるのかを規定するのがアクセス指定子です。 クラスの中ではアクセス指定子の右側に「:」を付けて、その下にメンバ関数やデータメンバを記述します。
クラスの中に宣言をした後は、メンバ関数の実際の中身をクラスの宣言の下(つまりクラスの外)に書いていきます。 例えばgetPoint関数は以下のように書いています。 クラスの宣言の中にメンバ関数の中身を書いていく方法もありますが、説明は後ほどします。
次にクラスの中のメンバ変数にデータを入れる方法について説明します。
この例ではクラス名をkeisanと名付けていますが、クラスはただの設計図なので、これにデータを入れないと何も動きません。
データを入れるには初めにのようにオブジェクトを作ります。この例では以下の箇所です。 オブジェクトを作った後はオブジェクト変数名にドット「.」を付け、その後にデータメンバを置きます。
そして、その中に代入演算子を使ってデータを入れていきます。
つまり、 という構文でデータを入れます。 そして、次はメンバ関数を呼び出しますが、実際にメンバ関数を呼び出しているのは以下の箇所です。 tasu関数の中では入力した数が0より大きくて、200より小さい値だった場合、number変数にb変数の値を足したものをnumber変数に代入しています。
数値がそれ以外の数だった場合は が実行されてでプログラムを終了させています。
次はobj.hiku(num2);の部分を説明します。 ここでは入力した数が0より大きくて、200より小さい値だった場合、number変数からc変数の値を引いたものをnumber変数に代入しています。
number -= c;はと同じ意味なので、tasu関数で計算されたnumber変数の値からC変数を引いた値をnumber変数に代入しています。
number変数にはtasu関数で計算された値が入っているので、hiku関数ではその値が使われます。
num1に5が入っているとするとの箇所でnumberには5と12が足された数値である17が代入されます。 num2に1が入っているとするとの箇所でnumberには17から1を引いた数値である16が代入されます。
numberには上の3番で17が入っていますので、この値が使われます。 getPoint関数はnumber変数の値を返すためだけに存在します。
次の例はアクセス指定子に「private」を指定した例をみてみましょう。 この例ではnumberにprivateを指定しています。
privateもpublicと同じくアクセス指定子です。
クラスの定義の中にデータメンバやメンバ関数を記述する時にはアクセス指定子を書くことになりますが、省略も出来ます。省略した場合にはデータメンバ、メンバ関数はprivateになります。 publicは同じクラスはもちろん他のクラスからもデータメンバやメンバ関数にアクセスすることが出来ます。
privateの付いたデータメンバにはクラスの外から直接アクセスできないので、メンバ関数からアクセスすることになります。
この例のnumber変数はprivateなので、以下のsetNumber関数からnumber変数に値を入れています。 ここで補足をしておきます。
publicやprivateはデータメンバやメンバ関数に付けますが、基本はデータメンバはprivateで、メンバ関数はpublicで指定します。
データメンバをpublicにするとどのような値でも入れることが出来るので思わぬ誤作動につながる可能性があります。
ですのでsetNumber関数のような関数を作って中身のをしてからデータメンバに値を代入する方が安全です。 次は関数の引数としてオブジェクトを使用する方法について説明します。
では例をみてみましょう。 この例で説明したい箇所は以下のs2関数です。
このs2関数はメンバ関数ではない普通の関数です。
この関数にアクセスする方法について説明します。 ここでの注目点は仮引数がのようにオブジェクト変数になっていることです。
このようにオブジェクト変数でデータを受け取ることも可能になっています。
ですのでs2関数を呼び出すときには実引数にオブジェクトを入れます。 このオブジェクトを使って、普通の関数s2の中でのように書くことで、メンバ関数のtriangleArea関数やsqureArea関数などの関数を呼び出すことができるようになります。
ではこのプログラムの説明をしていきます。 結果は以下の通りです。 次の例ではコンストラクタと言う機能を学びます。 コンストラクタとはオブジェクトを作成すると必ず呼び出される特殊な関数です。
データメンバをオブジェクト作成と同時に初期化したい時にコンストラクタを使用します。
オブジェクトを作成と同時に初期化することでデータメンバに対してデータを入れ忘れることはなくなります。
以下の箇所がコンストラクタですが、numberを初期化しています。 コンストラクタの基本構文は以下の通りです。 引数があれば書きますが、無ければ書かなくても結構です。
引数を書かない場合にはコンストラクタの中でのように直接データを入れます。 引数のあるコンストラクタは以下の箇所です。 そして、コンストラクタは必ずクラスの宣言の中のpublicの中で宣言をしてください。
次にコンストラクタを呼び出す方法について説明します。
基本構文は以下の通りです。 この例のコンストラクタの呼び出しは引数が無い場合にはのように引数なしで記述し、データを渡したい時にはのように引数を書いています。
「keisan obj;」で呼び出されるコンストラクタは以下の箇所です。 「keisan obj2(5); 」で呼び出されるコンストラクタは以下の箇所です。 このようにコンストラクタは引数の型や数が違うならば同じ名前のコンストラクタを複数定義することが出来ます。
この例では引数のあるコンストラクタと引数のないコンストラクタなのでオーバーロードが可能になっています。
結果は以下の通りです。 [補足2]
クラスの中にもインライン関数を書くことが出来ます。
通常、インライン関数を書くときにはinlineを付けますが、クラス宣言の中にインライン関数を書くときにはinlineを付けなくても、インライン関数としてみなされます。
以下の赤線で囲まれている箇所がインライン関数です。
通常の関数の書き方で書きます。
他のtasu関数などもクラスの中に書いても結構です。
この章ではオブジェクト指向型プログラミングについて説明します。
「オブジェクトリテラルについて知ろう」で説明したオブジェクトは配列と同じようなデータの集合体として説明しました。
しかし、オブジェクトをデータの集合体として使うだけだと大きなプログラムを作る時に少し不便です。
そこで、これから説明するオブジェクトを使った「オブジェクト指向型プログラミング」が必要になります。
JavaScriptのオブジェクト指向型プログラミングはPHPのような他の言語で使っているクラスの考え方とほぼ同じです。
JavaScriptの場合には関数が他言語でいうクラスの働きを受け持っています。
この本でもJavaScriptのオブジェクト指向型プログラミングをクラスと呼ばせていただきます。
クラスとは何かしらの物を作る設計図に例えられます。
設計図は車や家や鉛筆をつくる場合に必要ですが、この設計図に当たるものがクラスです。
車や家や鉛筆の中には色々な部品が含まれていますが、それらの部品には「状態」や「ふるまい」があります。
例えば、鉛筆であれば「状態」は鉛筆の形、芯、線の濃さなどで、「ふるまい」は線を引く、削るなどの動作です。
その「状態」や「ふるまい」をクラスと言う設計図に書いていきます。
「状態」を変数で書き、「ふるまい」を関数で書くことになります。
その「状態」や「ふるまい」に指示を出すのはオブジェクトです。
例えば「線を消す」など具体的な指示をオブジェクトと言う司令塔から出します。
「状態」は変数で書くと言いましたが、クラスの中の変数のことをプロパティと言います。
「ふるまい」は関数で書くと言いましたが、クラスの中の関数のことをメソッドと言います。
この「状態」や「ふるまい」に対して指示を出すのがオブジェクトの役割です。
このオブジェクトからプロパティにデータを入れたり、メソッドに指示を出すことになります。
例を見てみましょう。 ①関数が他言語でいうクラスの働きを受け持っていますと書きましたが、それが以下の箇所です。 つまり、ここが設計図になります。
この関数をに代入しますが、変数名は大文字で記述してください。
この変数名がクラス名になります。
②次はクラスのオブジェクトを作成します。 クラスのオブジェクトは「new演算子」を使って生成します。
先ほど「状態」「ふるまい」に対して指示を出すのがオブジェクトの役割ですと言いましたが、このオブジェクトから設計図の中のプロパティにデータを入れたり、メソッドに指示を出すことになります。
カッコの中の引数1000と2はクラスのプロパティを初期化するために存在します。
このようにオブジェクトを作成すると同時にプロパティが初期化される機能をコンストラクタといいます。 引数である1000と2がクラスのa,bにそれぞれ代入されます(1000がaに、2がbにそれぞれ代入されます)。
そして、にaが代入され、にbが代入されます。
次はthisについて説明します。
thisとはオブジェクト自身を指します。
this.kingakuはオブジェクト自身のkingakuにaを入れる
this.kazuはオブジェクト自身のkazuにbを入れる
と言う意味です。
つまり、thisを使って、オブジェクトとプロパティの関連付けを行なうと考えていただいて結構です。
次にクラスにメソッドを追加する方法について説明します(スペースの都合でreturn文を2行で書いていますが1行で書いても結構です)。 と言う形式でメソッドをクラスに追加します。
メソッドを入れる位置はの記述より後にします。
つまり、オブジェクトの後にメソッドを追加します。
この例ではという形式でメソッドを追加しましたが、最初から以下のようにfunction内に記述することも出来ます。 function内に書くときにはのようにthisを付けます。
では次の例をみてみましょう。 変数を追加するにはの形式で書きます。
最初から変数を設定しなくても後からでも追加できることを覚えておいてください。
この例ではの箇所です。
この変数をメソッド内で使用する時にはいつもの通り、thisを付けて使用します。
最後に以下の箇所で結果を出力します(スペースの都合で2行で書いていますが1行で書いても結構です)。 shop.getGoukei()と記述することで、計算結果が出力されます。
結果は「消費税は1000円です」です。
次の例でオブジェクトについての注意点を説明します。 ここではオブジェクトを以下のように2つ作成していますが、このようにオブジェクトは複数作成することが出来ることを覚えておいてください。 この例ではshopオブジェクトに以下のようにメソッドの追加をしていますが、これはshopオブジェクトに属しているもので、shop2オブジェクトに属しているわけではありません。 ですので以下のように記述しても、結果を得ることは出来ませんので注意してください。 次の例のように初めからfunction内にgetGoukeiメソッドを記述していれば上の文は問題なく出力できます。