Closed9

『スッキリわかるJava入門』の第Ⅱ部をよむ

Daigo WakabayashiDaigo Wakabayashi

第七章

  • オブジェクト指向はJavaの根幹となる思想
  • これからそれを学ぼう

7-1 なぜ学ぶのか

  • 大規模なプログラミングでは、プログラムそのものではなく、人間がソフトウェア開発のボトルネックになってしまうこともある
  • そのために誕生したのが「オブジェクト指向」
オブジェクト指向の目的
「人間が把握しきれない複雑さ」を克服する
  • 言語の文法などと違って「正解」を求めてはいけない、「考え方を学ぶ」という意識が大事
  • あと、一発で理解なんてできないから、何回も繰り返し意識して定着させよう

7-2 オブジェクト指向の定義と効果

定義

定義
オブジェクト指向とは、ソフトウェアを開発するときに用いる部品化の考え方のこと

賢い部品化をすることで「複雑なプログラムを人間が把握しやすくしよう」

効果

  • プログラムの変更がかんたんになる(柔軟性・保守性の向上)
  • プログラムの一部をかんたんに転用できる(再利用性の向上)

→ラクして、たのしく、良いものを作れるようになるで

7-3 オブジェクト指向の全体像と本質

  • プログラミングは「現実世界のなにかを自動化するため」に作られている

なんもかんがえずにコード書くのは「手続き型プログラミング」という
それに対してオブジェクト指向は、コードを書く前に、「そのプログラムを現実世界に置き換えて考える」らしい

オブジェクト指向における「部品化」のルール

現実世界に出てくる登場人物の単位で、プログラムをクラスに分割する
  • オブジェクト指向プログラミングにおいて、開発者は「Java仮想世界における神様」のような存在
  • 「指向」というのは「〜を大切にした」「〜を中心に据えた」という意味

オブジェクト指向の本質

「なぜ、オブジェクト指向の考え方で『人間が把握しやすくなり、ラクに開発できるようになるのか」

→「私達人間が慣れ親しんでいる「現実世界」をマネして作られたプログラムもまた、私達人間にとって把握しやすいものだから」

現実世界の登場人物とそのふるまいを、コンピュータ内の仮想世界で再現する。

7-4 オブジェクトと責務

  • オブジェクト指向プログラミングでは、開発者はそれぞれの部品(クラス)に「責務」をプログラムして落とし込む
  • それぞれのオブジェクトは「属性(情報保持責任)」と「操作(行動責任)」をもつ

7-5 オブジェクト指向の3大機能とその位置づけ

オブジェクト指向の3大機能
1. 継承
2. 多様性
3. カプセル化

注意点

  • 全部理解しようとするな
  • 特に「高度な継承」や「多様性」については2〜3集してから理解しよう
Daigo WakabayashiDaigo Wakabayashi

第8章

8-1

設計図がクラス、そこから作り出された実態がオブジェクト(またはインスタンス)という

8-2

クラスの定義方法、だいたいわかっているので読み飛ばした

8-3

Person kboy;
Person Daigo;

こんなやつをクラス型変数とよぶ

8-4

現実に似せて作り、現実に似せて動かすのが大事

Daigo WakabayashiDaigo Wakabayashi

9章

9-1

インスタンスは単なるメモリ領域

インスタンス化の中で起きていること

Hero h;
h = new Hero();
h.hp = 100;

Step1: 変数領域の確保

Hero h;

メモリ内に領域を用意するが、中にはなにも入っていない

Step2: Heroインスタンスの生成

h = new Hero();

これでインスタンスが生成される

が、Hero内の変数(name、hp)は空

Step3: 参照の代入

h = new Hero();

ここで行われていることは、
実際は「インスタンスの生成」ではなく
「new によって生成されるインスタンスのために確保されたメモリの先頭番地」である

「番地の情報からHeroインスタンスの詳しい情報を参照する」形式で参照型と呼ばれる(うーん、理解度60%くらい)

Step4: フィールドへの値の代入

h.hp = 100;

この行のJVMの解釈は
①変数hの内容を調べると、「3922番地を参照して」と書かれている
②メモリ内の3922番地にあるインスタンスのメモリ領域にアクセルし、その中のhpフィールド部分を100に置き換える

↑この動作を「アドレス解決」といったりするで

9-2

コンストラクタとは

class Person{
   String name;
   int age;

   Person ({
      this.name
      this.age
   })↑コレ

}

コンストラクタとみなされる条件

①メソッド名がクラス名と完全に等しい
②メソッド宣言に戻り値が記述されていない
Daigo WakabayashiDaigo Wakabayashi

10章

10-1

継承すると、元クラスの変数やメソッドが使える。
差分だけを記述して新たなクラスを宣言できる

親クラスに同じメンバがなければ「追加」
親クラスに同じメンバがあれば「上書き変更」

宣言時にfinalつけたら継承できない(ex:Stringは継承できない)

10-2

superをつけると親クラスのメソッドやフィールドにアクセスできる

10-3

is -a の関係(子は親の一種)じゃないと継承しては行けない

Daigo WakabayashiDaigo Wakabayashi

11章 -高度な継承-

抽象的なクラスを正しく、安全に、便利に利用するために準備されているクラスの定義方法を紹介する

11-1

「抽象度の高いクラス専用」の定義方法を学んでくよ

高度な継承は「立場」が違う

今までは「親から子を継承する」立場での話
これからは「子を作りやすい親をつくる」立場での話

高度な継承(抽象クラス、インターフェース)は「継承元となる親クラスを安全便利に定義するための道具」なのです

11-2

普通に親クラスを作るだけでは以下のような不都合と心配事が出てくる

- 不都合:詳細未定のメソッドがでてくる
  - 心配事①:オーバーライド忘れ
  - 心配事②:「なにもしない」との区別(本来の意味を失う)

- 不都合:クラスには2つの利用方法(new(←たぶんdartは書かなくてもいいが)、extends)があり、開発者はそれを選ぶことができる
  - 心配事③:意図しないインスタンス化を招く(抽象設計のままインスタンス化されてしまう)

11-3

心配事②を解決したい

  - 心配事②:「なにもしない」との区別(本来の意味を失う)

抽象メソッドの宣言にはabstractを使う

これをつけると、「宣言すべきではあるが、具体的になにをするかは未設定」というメソッドが作成できる

心配事②は解決

心配事③を解決したい

  - 心配事③:意図しないインスタンス化を招く(抽象設計のままインスタンス化されてしまう)

abstractメソッドを持ったクラスは、abstract class Charactor ... のように宣言しないといけなくなる
これを「抽象クラス」という

抽象クラスは「インスタンス化できない」という制約をもつ
→継承の材料としてでしか使えない

心配事③が解決

心配事①を解決したい

  - 心配事①:オーバーライド忘れ

abstractメソッドは、「具体的なメソッド内容を記述しないとエラーになる」ため
オーバーライドを強制できる

心配事①が解決

多重継承

インスタンス化されるまでにすべての抽象メソッドが埋まっていればよいので

  • モンスター
    • 飛ぶモンスター
      • 吸血コウモリ
      • 凶暴プテラ
    • 歩くモンスター
      • ゴブリン
      • 金棒ゴブリン

のように、多重継承を行って、「だんだん具体化させていく」ということもできる。

11-4 インターフェース

インターフェースとは

①すべてのメソッドが抽象メソッド
②フィールドをひとつも持たない

を満たす抽象クラスのこと(Dartにはinterfaceは無いらしいがimplementsを使うとどうようのことができる)

インターフェースと聞くと難しく聞こえるが、大事なのは「しょせん抽象クラスみたいなもの」という意識

class クラス名 implements インタフェース名 {
 :

}

インターフェースの効果

①インターフェースを implements する複数の小クラスたちに、共通のメソッド軍を実装するよう強制できる
②あるクラスがインターフェースを実装していれば、少なくともそのインターフェースが定めたメソッドはもったいることが保証される

クラスにはないインターフェースの特権

→多重継承が認められている

単純な「クラスの多重継承」では、異なる内容のメソッドが衝突する問題が発生するが、インターフェースではabstractとして定義されているため、メソッド内容をオーバーライドせねばならず、衝突が発生しないから

同種(クラス同士、インターフェース同士)の継承の場合はextendsを使う
異種ならimplementsを使う

Daigo WakabayashiDaigo Wakabayashi

12章 多態性

継承では「あいまいな物事」をコードとして表現できることを学んだ
本章では、物事を「あいまいにとらえる」ための機能です

12-1 多態性とは

今はあいまいなイメージでいこう

「あるものを、あえてザックリ捉える」ことでいろんなメリットを享受しようという機能。

12-2 ザックリ捉える方法

特別な文言などは特に必要なく、以下のように書く
Character → Hero → SuperHero

普通のインスタンス化

SuperHero h = new SuperHero();

ざっくり捉える

Character c = new SuperHero();

左辺は捉え方、右辺は実体を指す。

  • 抽象クラスやインターフェースから、インスタンスを生み出すことはできないが、それらの型を利用することは可能↓(左辺部分(捉え方)には使える)
Life lf = new Wizard();

12-3 ザックリ捉えたものに命令を送る

左辺部分につかったクラスのメソッドしか使えないよ(たとえ右辺の実体がメソッドをもっていたとしても空は無理)

左辺→どのメソッドが「呼べるか」を決定する
右辺→どのメソッドが「動くか」を決定する

12-4 捉え方の変更

キャストは結構危ない
そのために「実体がなにか」を確認する記法がある

12-5 多態性のメリット

ザックリ捉えて一括で指示を書ける(ポケモンセンターで全モンスターのHP回復とか)

呼び出し側は相手を同一視し、同じように呼び出すのに
呼び出される側は、きちんと自分に決められた動きをする

Daigo WakabayashiDaigo Wakabayashi

カプセル化

13-1 カプセル化の目的をメリット

カプセル化とは、メンバ(フィールドやメソッド)に対してアクセス制御をかけることで、悪意や間違いによる利用を防止する仕組み

13-2 アクセス制御

Javaでは
①自分自身のクラスのみ
②自分と同じパッケージに属するクラス
③自分と同じパッケージに属するか、自分を継承したクラス
④すべてのクラス

という4段階のアクセス制御レベルがある

dartでは

メンバにはアクセス制限をつけることが出来る。Javaのようにpublic、protected、privateのようなキーワードはなく、
Dartでは名前の頭に_(アンダースコア)をつけるとprivateとなる。
privateなメンバはクラス外からアクセスできない。(可視性の制御)

https://qiita.com/tokkun5552/items/4649478803be47cd488c#アクセス修飾子

getter と setter のメリット

①ReadオンリーWriteオンリーのフィールドを作れる
②フィールドへのアクセルを検査できる

Daigo WakabayashiDaigo Wakabayashi

感想

オブジェクト指向の概念を理解するのに良いと思った。
図解でイメージしやすく、これにはこういうメリットがあるというのが具体的にわかりやすく解説されており「なぜオブジェクト指向でつくるのか」がつかめる。
ただ注意点として、記法はDartと違う(当たり前だが)ので、あくまで概念的な理解を目的として読むのが良さそう。
Dartでの具体的な記法とかは以下の徳田さんの記事を読むのがよさそう

https://qiita.com/tokkun5552/items/4649478803be47cd488c

このスクラップは2021/06/27にクローズされました