19.0428

継承2(override, プロパティ/メソッド の追加)
thisキーワード
ローカル変数とは?


1. thisキーワード と ローカル変数
thisキーワード については、出会う度に、
簡単な解説を加えましたが、ここで、キッチリ理解しておきましょう。
thisキーワード は、とても便利に使えるので、早めに覚えておいた方がいいです。
多分、解説が重複するとは思いますが、ここでは、
  メソッドの引数 と、プロパティ(フィールド) の、名前が重なる場合
での、特に、紛らわしい場合のコードを使って見てみましょう。
いずれは、このコードを見て、すんなり分かるようになりたいものですが、
最初は、カラーを使って、分かりやすくしたコードを、見てみましょう。

そもそも、thisキーワード は、何のために使うのでしょうか?
this の、「この」 とは、「thisキーワード を含んでいる class」 を、指します。
つまり、
  今、this と、書いているclass 自身
です。
そして、
  this.変数
と書けば、「このクラスの変数」 という意味ですね、、つまり、
  プロパティ/フィールド を指す
ことになります。
また、
  this.関数
と書けば、「このクラスの関数」 という意味になり、すなわち、
  メソッド を指す
ことになります。
そうです、
  フィールド と メソッド に、特定するため
に使うのです。
特に、
  名前が同じ変数 が、登場した時は、
  this を、付けて、フィールド/プロパティ ですよ!
と、言っているわけです。
これは、
  メソッドの、仮引数である変数名 と、特に、被りやすい
です!

では、先ほどのコードを、見て考えてみましょう。
Catクラス の、
  3行目で、
  name
を、定義しています。
これは、
  class なになに { フィールド変数 { ローカル変数 } }
のように、
  最初の{ } の中に、定義されているので、
  フィールド/プロパティ 変数
になります。
もし、
  2番目以降の{ } の中にある場合は、
  ローカル変数
という事になります。(これは、ここで覚えましょう)

これに対して、
  4行目の、
  name
は、
  メソッド の 引数 の位置に在って、
分かりにくいですが、
  ローカル変数になる
のです。
すると、
  それより、内側の { } の中 は、
  ローカル変数nameになる
のです、、これは、{ } が、変数の範囲 を、決めているからです(スコープ/scope といいます)。

さて、これからが、thisキーワード が、活躍するところです。
  7行目で、
  プロパティ変数、name を、使いたい時
  どうすればいいでしょうか?
もう分かったと思いますが、
  もし、name と、書いてしまえば、
  ローカル変数name に、なる
ことは、今言ったとおりです。
ですので、
  thisを付けて、
  this.name
とすれば、
  プロパティ(変数)
という事になります。

ここで、キッチリ、thisキーワード を、覚えましょう。


2. 継承したクラスに オーバーライド と プロパティ・メソッドの追加
前回、
 open class 親クラス名(コンストラクタ)

 class 子供クラス名( 引き継いだコンストラクタval/varは不要, [任意:val/var 新たな変数: 型] )
  : 親クラス名( 変数名のみ )

という形式で、
  親クラス のクローンである 子供クラス
を、作成しました。
クローンを作ることは、新しいクラスに変身させる第一歩ではありますが、このままでは、
何のために、継承したか分かりませんね。

子供クラス を、実用的なクラスにするためには、
  オーバーライド/override や プロパティ・メソッドの追加
が、必要です。

前回のコード に、
  プロパティの追加 と、メソッドのオバーライド
を、実行したのが、こんなコードです。
(もし、小さすぎたら、こちらで見てください


プロパティ・メソッド の追加
まずは、
  メソッドの追加
から、見ていきましょう。
これは、簡単で、
  単に、メソッドを追加するだけ
です。
  21~24行目の、
  showColor()メソッド
を、見てください。
ここで、
  color
は、
  仮引数で、ローカル変数
で、
  this.color
が、
  DeluxeCarクラス の プロパティ
であることは、先の、thisキーワード の、学習で、理解できると思います。

では、
  this.color が、DeluxeCarクラス の、
  プロパティ であること
は、どこで判断しているのでしょうか?
それは、
  18行目の、
  class DeluxeCar(maxGasoline: Double, var color: String) : Car(maxGasoline)
  DeluxeCarクラス の コンストラクタ
で、定義しました。
(ここで、color に、﹏ があるのは、IntelliJ が、privateキーワード を、使うように提案しているからですが、
 privateキーワード は、後に、学習します)

ここで、
  maxGasoline には、var/val を使っていない
のに、
  color には、varキーワード を使っている
のは、
  maxGasoline は、単に、Carクラス から 引き継いでいるだけ
なのに対して、
  color は、ここで、新たに定義 しているから
です。
もう一度、今の話を振り返ると、
  プロパティ追加の方法
  メソッド追加の方法
についてでした。


オーバーライドする
そもそも、オーバーライド(override) とは、なんでしょうか?
それは、親クラスのメソッド を、上書きすることです。
子供クラス の、事情に合わせて、上書きをするという事です。

そのためには、
  1. 親クラス で、オバーライド したい メソッドに、openキーワードを付けること.
  2. 子供クラス で、オーバーライド するメソッドに、overrideキーワードを付けること.
この2つが、必要です。
さらに、
  3. メソッド名・引数・戻り値 は、親クラスのメソッドに、一致させること
   (要は、全く同じスタイルでないと、オーバーライド とは、見なされない!)
   (逆に、open, overrideキーワードを、付けずに、オーバーライドしても、不正だとみなされる!)

ここでは、
  26行目の、theRest()メソッド(残り燃料を、Doubleで返します)
で、
  オーバーライド
しています。
どこを書き換えているのか、違う部分を、並べてみます。
  Carクラス (12行目):
    return maxGasoline - (drivenKilometers / 10.0)
  DeluxeCarクラス (28行目):
    return maxGasoline - (drivenKilometers / 5.0)
この意味は、
  return ガソリン総量 ー (運転した距離 ÷ リッター当たり何キロ走るのか)
    / つまり、ガソリンの残量 に、なります.

このように、親クラス の、メソッド を、上書きすることが、override です。



まとめ
thisキーワード を使うと、プロパティ・メソッド であることを示せる。
   / 使い方: this.変数/関数
ローカル変数 とは:
   あるClass {
     プロパティ
     fun あるメソッド(仮引数/ローカル変数でもある: 型): 戻り値の型 {
       ………
       ………ある変数/ローカル変数
       ………
       return 戻り値
     }
   }
子供クラス に、プロパティ を、コンストラクタ に追加する時には、val/var キーワード が、必要である!
   例: class DeluxeCar(maxGasoline: Double, var color: String) : Car(maxGasoline)
・ 子供クラスに、メソッドの追加 をするには、単に、メソッド を書けばよい
オーバーライド(override) とは、親クラスのメソッド を、上書きすることです。
オーバーライドをする時の規則
   1. 親クラス で、オバーライド したい メソッドに、openキーワードを付けること.
   2. 子供クラス で、オーバーライド するメソッドに、overrideキーワードを付けること.
   3. メソッド名・引数・戻り値 は、親クラスのメソッドに、一致させること
   (要は、全く同じスタイルでないと、オーバーライド とは、見なされない!)
   (逆に、open, overrideキーワードを、付けずに、オーバーライドしても、不正だとみなされる!)