Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Javaプログラミング入門
第5回
今日の内容
• 前回の復習
• スーパークラスとサブクラス
クラスとインスタンス
クラスとインスタンス
• クラスのインスタンスは共通の性質を持つ
Stringクラス
Stringのインスタンス
Stringのインスタンス

"田中"

"Hello World! "
Stringのインスタンス
"Java"
インスタンス
• インスタンス(instance)は具体的な「特定のも
の」を表す
• すべてのインスタンスはクラスに属している
• インスタンスのことを「オブジェクト」と呼ぶ
こともある。
クラスを宣言する
• 新たなクラスを作ること→「クラスを宣言す
る」
• クラス名は大文字で始めるのが慣習
class クラス名 {
フィールドの宣言
メソッドの宣言
}
フィールド
• 情報を保存する場所を指す
• 「幅」「高さ」という2つの長方形の情報を持つ
クラス
class Rectangle {
int width:
int height;
}
• この時、widthやheightをフィールドと呼ぶ
•...
メソッド
• 情報を処理する方法
• 長方形を表すRectangleクラスに以下のメソッド
を追加する
▫ 幅と高さを設定する(setSize)
▫ 面積を計算する(getArea)
Rectangleクラス
class Rectangle {
int width;
int height;
void setSize(int w, int h) {
width = w;
height = h;
}
int getArea() ...
インスタンスの作り方
• Rectangleクラスのインスタンスを作るには、
new演算子を使う

new Rectangle()
• newはjavaの予約語
• 作ったインスタンスをRectangle型として宣言し
た変数に代入する
Rec...
フィールドへのアクセス
Rectangle r = new Rectangle();
r.width = 123;
r.height = 45;
Rectangle型の変数r+「.(ドット)」+Rectangleク
ラスのフィールドwidth
...
メソッドの呼び出し
Rectangle r = new Rectangle();
r.setSize(123, 45);

• rのsetSizeメソッドを呼び出し、第1引数を123、
第2引数を45をせよ
• 「メソッドを呼び出すときに与える...
Rectangleのコンストラクタ
public Rectangle(int w, int h) {
width = w;
height = h;
}
• メソッドと似ているが異なる点が2点
1. コンストラクタには戻り値の型がない(voidで...
コンストラクタを呼び出す
Rectangle r = new Rectangle(123, 45);
• 幅123、高さ45のRectangleのインスタンスが生
成され、変数rに代入された
フィールドの初期化
• 単にフィールドを初期化するだけなら、コンス
トラクタの中で設定せずに、フィールド宣言の
ところに初期値を記述すればよい
int width = 10;
int height = 20;
クラスフィールドとは
• 「インスタンスに個別の番号をつけるにはどう
したらよいか?」
class Rectangle {
int number;
Rectangle() {
number = ...
}
}
• numberフィールドはどこに...
全インスタンス共通のどこかに情報を
保持しておくには?
• numberフィールドは、新たに作られたばかりの
インスタンスの中にあるフィールド
• つまり、自分以外のインスタンスがどれくらい
あるのかわからない
• 全体を俯瞰して見る場所が必要...
クラスフィールドの宣言
class Rectangle {
static int counter = 0;
}
• 通常のインスタンスとは異なり、staticという修
飾子が付く
• staticは「静的な」という意味
クラスフィールドを使ってインスタン
スに番号をつける
class Rectangle {
...
static int counter = 0;
int number;
Rectangle() {
...
number = counter;
c...
クラスメソッドの宣言
• メソッドにもインスタンス同様staticを使ったクラ
スメソッドがある
• 「これまでに作られたRectangle インスタンスの個
数を得る」メソッドgetCounter
class Rectangle {
stat...
クラスメソッド
• staticをメソッドに付けるとクラスメソッドにな
る
• クラスメソッドは特定のインスタンスと関連付
けられていない
• 「現在のインスタンス」thisを使うとコンパイ
ルエラー
• superを使ってもコンパイルエラー
...
クラスメソッドとインスタンスメソッ
ド
• GamePlayerクラスで「生きているプレイヤーの数」を
得るcountAlivePlayerはクラスメソッド。これに対して、
「現在のプレイヤーが生きているかどうか」を調べるの
isAliveメソ...
クラスメソッドの呼び出し
• クラスメソッドは特定のインスタンスに紐付か
ないので以下のようにアクセス出来る

• クラス名.メソッド名(引数列)
演習5
• Rectangleのインスタンスの内容が等しいかどう
かを調べるメソッドが必要になり、areSameメ
ソッドを作った。しかし、先生に見せたところ、
「引数を1つにした方がいい」と言われた。どう
すればよいか。
Rectangleクラス
class Rectangle {
...
// 2つのRectangleを比較して、等しかったらtrue,
// 等しくなかったらfalseを返す
boolean areSame(Rectangle a, Recta...
演習6
• これまでのRectangleクラスの宣言では、width
やheightの値がマイナスであるかどうかの
チェックが入っていない。ここで、widthと
heightがマイナスになるなら、強制的に0になる
ように既存のRectangle...
演習7
• これまでのRectangleクラスは、幅と高さを持つ
長方形だったが、これに「左上すみの位置」を
表すxとyというフィールドを追加し、以下のコ
ンストラクタやメソッドを宣言しなさい
1. フィールド
1. 指定がないときの幅と高さ
...
演習7(続き)
2. コンストラクタ
1. 引数がないもの(width, heightの初期値は
INITIAL_WIDTH,INITIAL_HEIGHT,xとyは0)
2. width,heightだけを指定したもの(xとyは0)
3. x,...
演習7(続き)
3. メソッド
1. 位置を指定するvoid setLocation(int x, int y)メソッ
ド
2. 大きさを指定するvoid setSize(int width, int
height)メソッド
3. [x, y,...
スーパークラスとサブクラス
• すでに存在するクラスをもとにして、新しいメ
ソッドやフィールドを追加したり、すでにある
メソッドを上書きしたりして、新しいクラスを
作ることが出来る → クラスの『拡張』
• クラスを拡張してできた新しいクラスを...
スーパークラスとサブクラス
長方形

名前付き
長方形

Rectangle

NamedRectangle

NamedRectangleの
[スーパークラス]

Rectangleの
[サブクラス]
スーパークラスは1つ
• Javaでは2つ以上のクラスをスーパークラスにす
ることはできない
• スーパークラスは複数のサブクラスを作ること
が出来る
クラス階層
classA

classB

classE

classC

classF

classD

classG

classH
extendsでスーパークラスを指定
class NamedRectangle extends Rectangle {
}
• extendは『拡張する』という意味
Objectクラスとクラス階層
• すべてのクラスの共通の祖先はObjectクラス
• Objectクラスは、すべてのクラスの中で唯一
スーパークラスを持たない
• クラスは、スーパークラスを指定せずにクラス
宣言すると、自動的にObjectク...
継承
• サブクラスはスーパークラスのフィールドとメ
ソッドを引き継ぐ。このことを継承と言う
フィールドの継承
• スーパークラスの持つフィールドをサブクラスで持つ
• NamedRectangleのインスタンスnrを介して、フィールドを参照・
代入することが出来る
• NamedRectangle.java
public class ...
メソッドの継承
• NamedRectangleクラスはRectangleクラスのメソッドを
呼び出すことが出来る
public class NamedRectangle extends Rectangle {
public static vo...
コンストラクタは継承されない
• フィールドとメソッドは継承されるが、コンストラクタは継承され
ない
• NamedRectangle.java
public class NamedRectangle extends Rectangle {
S...
コンストラクタの呼び出し
• 正しいコンストラクタの呼び出し
public static void main(String[] args) {
Rectangle r = new Rectangle();
Rectangle s = new R...
コンストラクタの呼び出し
• NamedRectangleクラスにコンストラクタを定義
していないため、コンパイル時エラーとなる
NamedRectangle nr = new
NamedRectangle(67,890);
コンストラクタが継承されない理由
• コンストラクタがインスタンスの初期化を担っ
ているため

• 例えば
NamedRectangle nr = new
NamedRectangle(67,890);
が呼び出せたとすると、NamedRect...
コンストラクタの自動的な呼び出し
• 先ほどのコンストラクタNamedRectangle()の中
では、フィールドnameは初期化されているが、
スーパークラスから継承されているwidth、
heightは初期化していない
• サブクラスのコン...
コンストラクタの自動的な呼び出し
• NamedRectangle.java
public class NamedRectangle extends Rectangle {
String name;
NamedRectangle() {
// ...
誰が何を挿入するのか?
• スーパークラスのコンストラクタの呼び出しを
自動に挿入するのは誰か?
▫ Javaのコンパイラの仕事

• 何が挿入されているのか?
▫ new Rectangle()では、現在初期化しようとするイ
ンスタンスとは別...
super()
• スーパークラスのコンストラクタの明示的な呼
び出し
NamedRectangle() {
super(); // スーパークラスの引数なしコンスト
ラクタ
name = "NO NAME";
}

• スーパークラスの引数な...
super()
• コンストラクタの中から、スーパークラスの引
数付きのコンストラクタを呼び出したい時
▫ NamedRectangle nr = new
NamedRectangle("name"); というインスタンスを
作る時、長方形の大...
this()
• 自分のクラスのコンストラクタの明示的な呼び出しが出来る
public class NamedRectangle extends Rectangle {
String name;
NamedRectangle() {
this(...
this()
• this("NO NAME");
▫ もう1つのコンストラクタNamedRectangle(String
name)を呼び出している

• this()を使うとコンストラクタがたくさん定義さ
れていても、初期化処理を共通化する...
演習1
• 次の機能をもつPlacedRectangleをRectangleの
サブクラスとして宣言しなさい。また、
Rectangleは次スライドに定義されている
▫ 位置を表すint型のフィールドx,yを持つ
▫ 3つのコンストラクタを持つ...
Rectangle.java
class Rectangle {
int width;
int height;
public Rectangle() {
setSize(0, 0);
}

Rectangle(int w, int h) {
s...
継承とIS-A関係
• サブクラスがスーパークラスの性質を受け継ぐ
▫ 『サブクラスはスーパークラスの一種である』
▫ 『○○は○○の一種である』→IS-A関係
classA

classB
classD
classC

classE
多重継承
• Javaでは多重継承はサポートしていないが、イ
ンタフェースという機能を使って擬似的に多重
継承を実現することが出来る
合成とHAS-A関係
• NamedRectangleクラスは、String型のフィール
ドを持っていた
▫ String型のインスタンスを自分の名前として持っ
ていた
▫ インスタンスをフィールドとして持つと、そのイ
ンスタンスを自分の物とし...
継承の目的
• 親の財産を受け継ぐことができれば、子供はゼ
ロからスタートしなくてもよい
• クラスの継承も同じく、ゼロからではなく、既
存のクラスを拡張してプログラミングすれば時
間の効率化、バグ改修を少なくすることが出来
る
オーバーライド
• クラスは、スーパークラスのメソッドを継承す
るが、新たなメソッドを追加するだけでなく、
継承したフィールドやメソッドを変更すること
が出来る。このような変更をメソッドのオー
バーライドと言う
メソッドのオーバーライド
public class NamedRectangle extends Rectangle {
...

@Override
void setSize(int width, int height) {
...
}
}
メソッドのオーバーライド
NamedRectangle nr = new NamedRectangle();
// NamedRectangleのインスタンス生成
nr.setSize(56, 78);
// NamedRectangleのse...
シグニチャ
• メソッドをオーバーライドするには、サブクラ
スで『同じメソッド』を宣言する必要がある
• 『同じ』とは
▫ メソッドの名前が等しい
▫ 引数列の型が等しい

ことを意味する
• この『メソッド名と引数列の型』のことをメ
ソッドの...
@Override
• @から始まるものをアノテーションと言う
• 単なるコメントではなく、コンパイラも理解す
るコメント
• @Overrideの場合は、メソッド名の綴りミスな
どによるオーバーライドの失敗をコンパイラが
チェックしてくれる
演習2
• 演習1で作成したPlacedRectangleクラスに以下
のメソッドを追加しなさい
▫ 標準的な文字列表現を返すメソッドtoString
 x = 12, y = 34, width = 56, height = 78のとき、
...
コントラクトは変更してはいけない
• あるクラスの『フィールドとメソッドが持つ意
味』をコントラクト(契約)という。
• オーバーライドしたメソッドを書き換えること
が可能だが、そのフィールドやメソッドの意味
(コントラクト)を変更してはいけな...
オーバーライドとオーバーロード
• オーバーライドはスーパークラスのメソッドを
変更すること。オーバーライドは『命令を無効
にする』『決定を覆す』という意味。上書き宣
言。
• オーバーロードは同じ名前と異なる引数を持つ
メソッドを多数宣言する...
多態性とオーバーライド
• サブクラスのインスタンスは、スーパークラス
のインスタンスとしてみなすことが出来る
NamedRectangle nr = new
NamedRectangle("name");
このとき、変数nrはRectangl...
多態性とオーバーライド
• 犬のポチを『犬』としてではなく、『哺乳類』
として扱っている
• このように同じインスタンスが、変数nr経由で
はNamedRectangleとして扱われ、変数rでは
Rectangleとして扱われる
• このことを...
多態性とフィールド
nr.name 名前が得られる
nr.width 幅が得られる
nr.height 高さが得られる
r.name コンパイルエラー(Rectangleにname
フィールドはない)
r.width 幅が得られる
r.heig...
多態性とメソッド
r.setSize(56, 78);
• 通常は、RectangleのsetSizeメソッドが呼び出さ
れるが、NamedRectangleクラスにsetSizeメ
ソッドがあれば(オーバーライドされていれば)、
NamedR...
finalメソッドはオーバーライドできな
い
• finalが付いたメソッドはサブクラスにも継承さ
れるが、サブクラスでそのfinalメソッドを変更
すること(オーバーライドすること)は出来ない
継承とアクセス制御
• スーパークラスでprivateと書かれたフィールド
やメソッドはサブクラスに継承されない
▫ サブクラスからアクセスすることが出来ない

• このように、アクセスを許可したり禁止したり
する機構のことをアクセス制御と言う
privateフィールドとprivateメソッド
class Rectangle {
private int width;
private int height;
private void internalMethod(int width, i...
アクセスメソッド
• 一般的に、フィールドはprivateにすることが多
い →サブクラスによって不用意に変更される
ことを防ぐため
• フィールドをprivateにして、外から隠し(情報隠
蔽)、そのフィールドを参照/設定するメソッド
のこと...
アクセスメソッド
class Rectangle {
private int width;
private int height;
int getWidth() [
return width;
}
int getHeight() {
retur...
クラスライブラリとパッケージ
• プログラミングに有用なクラスは、Java言語処
理系に数多く用意されている。このクラスの集
まりをクラスライブラリと呼ぶ
• 関連のあるクラスのいくつかを1つのグループに
まとめることも出来る。まとめられたグル...
finalクラスと拡張の禁止
• クラスを宣言するとき、final修飾子を付けるとその
クラスの拡張は禁止される
final class MyClass {
...
}
• クラスを拡張すると、セキュリティ上問題がある場
合や、プログラムの整合...
抽象クラス
• メソッドの名前と引数の方だけが定まっていた、
その本体(実装)がないメソッドのことを抽象メ
ソッド(abstractメソッド)という
• 抽象メソッドを含んでいるクラスを抽象クラス
(abstractクラス)と呼ぶ。
• 抽象ク...
抽象クラス
abstract class Player {
public abstract void play();
public void loop(int n) {
for (int i = 0; i < n; i++) {
play();...
playメソッドの実装
public class TextPlayer extends Player {
String text;
public TextPlayer(String text) {
this.text = text;
}
@Ov...
抽象クラスはサブクラスに期待する
• 抽象クラスは、自分で動作は規定しないけど、
どういうメソッドを宣言しなければならないか
をサブクラスに強要する
• 抽象クラスをうまく使うとサブクラスのメソッ
ド名が揃うため、読みやすいプログラムを書く
こ...
Numberクラスの場合
抽象メソッド
intValue()
longValue()
byteValue()
doubleValue()
...

Object

Number

Integer

Long

Byte

Double

メソッ...
演習3
• PlacedRectangleをRectangleのサブクラスとし
てではなく、Rectangle型のインスタンス変数を
持つクラスとして宣言しなさい
演習4
• 以下のプログラムを実行するとき、どのように表示
されるか考えなさい
class A {
A() {

System.out.println("1:A()");

}
A(int x) {
System.out.println("2:...
演習4
public class B extends A {
B() {
System.out.println("3: B()");
}
B(int x) {
System.out.println("4: B(int x)");
}
B(Str...
参考文献
• Java言語 プログラミングレッスン[第3版]下
▫ 結城浩[著]
Javaプログラミング入門【第5回】
Upcoming SlideShare
Loading in …5
×

Javaプログラミング入門【第5回】

1,211 views

Published on

継承、オーバーライド、ポリモルフィズム

  • Be the first to comment

  • Be the first to like this

Javaプログラミング入門【第5回】

  1. 1. Javaプログラミング入門 第5回
  2. 2. 今日の内容 • 前回の復習 • スーパークラスとサブクラス
  3. 3. クラスとインスタンス
  4. 4. クラスとインスタンス • クラスのインスタンスは共通の性質を持つ Stringクラス Stringのインスタンス Stringのインスタンス "田中" "Hello World! " Stringのインスタンス "Java"
  5. 5. インスタンス • インスタンス(instance)は具体的な「特定のも の」を表す • すべてのインスタンスはクラスに属している • インスタンスのことを「オブジェクト」と呼ぶ こともある。
  6. 6. クラスを宣言する • 新たなクラスを作ること→「クラスを宣言す る」 • クラス名は大文字で始めるのが慣習 class クラス名 { フィールドの宣言 メソッドの宣言 }
  7. 7. フィールド • 情報を保存する場所を指す • 「幅」「高さ」という2つの長方形の情報を持つ クラス class Rectangle { int width: int height; } • この時、widthやheightをフィールドと呼ぶ • ここではまだクラス宣言しただけ
  8. 8. メソッド • 情報を処理する方法 • 長方形を表すRectangleクラスに以下のメソッド を追加する ▫ 幅と高さを設定する(setSize) ▫ 面積を計算する(getArea)
  9. 9. Rectangleクラス class Rectangle { int width; int height; void setSize(int w, int h) { width = w; height = h; } int getArea() { return width * height; } }
  10. 10. インスタンスの作り方 • Rectangleクラスのインスタンスを作るには、 new演算子を使う new Rectangle() • newはjavaの予約語 • 作ったインスタンスをRectangle型として宣言し た変数に代入する Rectangle r = new Rectangle();
  11. 11. フィールドへのアクセス Rectangle r = new Rectangle(); r.width = 123; r.height = 45; Rectangle型の変数r+「.(ドット)」+Rectangleク ラスのフィールドwidth • 「.(ドット)」は、日本語の「の」にあたる
  12. 12. メソッドの呼び出し Rectangle r = new Rectangle(); r.setSize(123, 45); • rのsetSizeメソッドを呼び出し、第1引数を123、 第2引数を45をせよ • 「メソッドを呼び出すときに与える引数」のこ とを実引数と言う • 「メソッドの宣言に書かれた引数」のことを仮 引数と言う
  13. 13. Rectangleのコンストラクタ public Rectangle(int w, int h) { width = w; height = h; } • メソッドと似ているが異なる点が2点 1. コンストラクタには戻り値の型がない(voidでもな い) 2. コンストラクタの名前はクラス名と同じ • コンストラクタの中から他のメソッド(setSize)を 呼び出してもよい
  14. 14. コンストラクタを呼び出す Rectangle r = new Rectangle(123, 45); • 幅123、高さ45のRectangleのインスタンスが生 成され、変数rに代入された
  15. 15. フィールドの初期化 • 単にフィールドを初期化するだけなら、コンス トラクタの中で設定せずに、フィールド宣言の ところに初期値を記述すればよい int width = 10; int height = 20;
  16. 16. クラスフィールドとは • 「インスタンスに個別の番号をつけるにはどう したらよいか?」 class Rectangle { int number; Rectangle() { number = ... } } • numberフィールドはどこにいる?
  17. 17. 全インスタンス共通のどこかに情報を 保持しておくには? • numberフィールドは、新たに作られたばかりの インスタンスの中にあるフィールド • つまり、自分以外のインスタンスがどれくらい あるのかわからない • 全体を俯瞰して見る場所が必要 ▫ Javaではクラスフィールド(クラス変数、スタ ティックフィールド)と呼ばれる宣言をすること で、全インスタンス共通の情報を保持することが 出来る
  18. 18. クラスフィールドの宣言 class Rectangle { static int counter = 0; } • 通常のインスタンスとは異なり、staticという修 飾子が付く • staticは「静的な」という意味
  19. 19. クラスフィールドを使ってインスタン スに番号をつける class Rectangle { ... static int counter = 0; int number; Rectangle() { ... number = counter; counter++; } }
  20. 20. クラスメソッドの宣言 • メソッドにもインスタンス同様staticを使ったクラ スメソッドがある • 「これまでに作られたRectangle インスタンスの個 数を得る」メソッドgetCounter class Rectangle { static int counter = 0; ... static int getCounter() { return counter; } }
  21. 21. クラスメソッド • staticをメソッドに付けるとクラスメソッドにな る • クラスメソッドは特定のインスタンスと関連付 けられていない • 「現在のインスタンス」thisを使うとコンパイ ルエラー • superを使ってもコンパイルエラー • staticではないメソッドをインスタンスメソッド と言う
  22. 22. クラスメソッドとインスタンスメソッ ド • GamePlayerクラスで「生きているプレイヤーの数」を 得るcountAlivePlayerはクラスメソッド。これに対して、 「現在のプレイヤーが生きているかどうか」を調べるの isAliveメソッドはインスタンスメソッド class GamePlayer { .... static int countAlivePlayer() { ... } boolean isAlive() { ... } }
  23. 23. クラスメソッドの呼び出し • クラスメソッドは特定のインスタンスに紐付か ないので以下のようにアクセス出来る • クラス名.メソッド名(引数列)
  24. 24. 演習5 • Rectangleのインスタンスの内容が等しいかどう かを調べるメソッドが必要になり、areSameメ ソッドを作った。しかし、先生に見せたところ、 「引数を1つにした方がいい」と言われた。どう すればよいか。
  25. 25. Rectangleクラス class Rectangle { ... // 2つのRectangleを比較して、等しかったらtrue, // 等しくなかったらfalseを返す boolean areSame(Rectangle a, Rectangle b) { if (a == null || b == null) { return false; } else if (a.width == b.width && a.height == b.height) { return true; } else { return false; } } }
  26. 26. 演習6 • これまでのRectangleクラスの宣言では、width やheightの値がマイナスであるかどうかの チェックが入っていない。ここで、widthと heightがマイナスになるなら、強制的に0になる ように既存のRectangleクラスを修正しなさい。
  27. 27. 演習7 • これまでのRectangleクラスは、幅と高さを持つ 長方形だったが、これに「左上すみの位置」を 表すxとyというフィールドを追加し、以下のコ ンストラクタやメソッドを宣言しなさい 1. フィールド 1. 指定がないときの幅と高さ (INITIAL_WIDTH,INITIAL_HEIGHT)
  28. 28. 演習7(続き) 2. コンストラクタ 1. 引数がないもの(width, heightの初期値は INITIAL_WIDTH,INITIAL_HEIGHT,xとyは0) 2. width,heightだけを指定したもの(xとyは0) 3. x,y,width,heightを指定したもの
  29. 29. 演習7(続き) 3. メソッド 1. 位置を指定するvoid setLocation(int x, int y)メソッ ド 2. 大きさを指定するvoid setSize(int width, int height)メソッド 3. [x, y, width, height]の形式で文字列として表現す るtoStringメソッド 4. 長方形の「重なり部分」(これも長方形)を得る intersect(Rectangle r)メソッド。ただし、重なり がない場合はnullを返す。重なりがある場合は、 長方形として返す。
  30. 30. スーパークラスとサブクラス • すでに存在するクラスをもとにして、新しいメ ソッドやフィールドを追加したり、すでにある メソッドを上書きしたりして、新しいクラスを 作ることが出来る → クラスの『拡張』 • クラスを拡張してできた新しいクラスを、もと クラスのサブクラス、もとのクラスをスーパー クラスと言う
  31. 31. スーパークラスとサブクラス 長方形 名前付き 長方形 Rectangle NamedRectangle NamedRectangleの [スーパークラス] Rectangleの [サブクラス]
  32. 32. スーパークラスは1つ • Javaでは2つ以上のクラスをスーパークラスにす ることはできない • スーパークラスは複数のサブクラスを作ること が出来る
  33. 33. クラス階層 classA classB classE classC classF classD classG classH
  34. 34. extendsでスーパークラスを指定 class NamedRectangle extends Rectangle { } • extendは『拡張する』という意味
  35. 35. Objectクラスとクラス階層 • すべてのクラスの共通の祖先はObjectクラス • Objectクラスは、すべてのクラスの中で唯一 スーパークラスを持たない • クラスは、スーパークラスを指定せずにクラス 宣言すると、自動的にObjectクラスのサブクラ スとして宣言される
  36. 36. 継承 • サブクラスはスーパークラスのフィールドとメ ソッドを引き継ぐ。このことを継承と言う
  37. 37. フィールドの継承 • スーパークラスの持つフィールドをサブクラスで持つ • NamedRectangleのインスタンスnrを介して、フィールドを参照・ 代入することが出来る • NamedRectangle.java public class NamedRectangle extends Rectangle { public static void main(String[] args) { NamedRectangle nr = new NamedRectangle(); nr.width = 78; nr.height = 910; System.out.println(nr.width); System.out.println(nr.height); } }
  38. 38. メソッドの継承 • NamedRectangleクラスはRectangleクラスのメソッドを 呼び出すことが出来る public class NamedRectangle extends Rectangle { public static void main(String[] args) { NamedRectangle nr = new NamedRectangle(); nr.setSize(78, 910); System.out.println(nr.getArea()); } }
  39. 39. コンストラクタは継承されない • フィールドとメソッドは継承されるが、コンストラクタは継承され ない • NamedRectangle.java public class NamedRectangle extends Rectangle { String name; NamedRectangle() { name = "NO NAME"; } } NamedRectangle(String name) { this.name = name; }
  40. 40. コンストラクタの呼び出し • 正しいコンストラクタの呼び出し public static void main(String[] args) { Rectangle r = new Rectangle(); Rectangle s = new Rectangle(123, 45); NamedRectangle nr = new NamedRectangle(); NamedRectangle ns = new NamedRectangle("name"); }
  41. 41. コンストラクタの呼び出し • NamedRectangleクラスにコンストラクタを定義 していないため、コンパイル時エラーとなる NamedRectangle nr = new NamedRectangle(67,890);
  42. 42. コンストラクタが継承されない理由 • コンストラクタがインスタンスの初期化を担っ ているため • 例えば NamedRectangle nr = new NamedRectangle(67,890); が呼び出せたとすると、NamedRectangleクラス のnameフィールドが初期化されないことになる
  43. 43. コンストラクタの自動的な呼び出し • 先ほどのコンストラクタNamedRectangle()の中 では、フィールドnameは初期化されているが、 スーパークラスから継承されているwidth、 heightは初期化していない • サブクラスのコンストラクタのはじめには、 スーパークラスの引数なしコンストラクタが自 動的に呼び出される
  44. 44. コンストラクタの自動的な呼び出し • NamedRectangle.java public class NamedRectangle extends Rectangle { String name; NamedRectangle() { // ここ name = "NO NAME"; } } NamedRectangle(String name) { // ここ this.name = name; }
  45. 45. 誰が何を挿入するのか? • スーパークラスのコンストラクタの呼び出しを 自動に挿入するのは誰か? ▫ Javaのコンパイラの仕事 • 何が挿入されているのか? ▫ new Rectangle()では、現在初期化しようとするイ ンスタンスとは別の新しいインスタンスが作られ てしまう ▫ スーパークラスのコンストラクタの呼び出しに特 別な表記法が用意されている
  46. 46. super() • スーパークラスのコンストラクタの明示的な呼 び出し NamedRectangle() { super(); // スーパークラスの引数なしコンスト ラクタ name = "NO NAME"; } • スーパークラスの引数なしコンストラクタの呼 び出しは省略することが出来る
  47. 47. super() • コンストラクタの中から、スーパークラスの引 数付きのコンストラクタを呼び出したい時 ▫ NamedRectangle nr = new NamedRectangle("name"); というインスタンスを 作る時、長方形の大きさをwidth=200,height=32 にしたい時は NamedRectangle(String name) { super(200, 32); // スーパークラスの引数 付きコンストラクタの呼び出し this.name = name; }
  48. 48. this() • 自分のクラスのコンストラクタの明示的な呼び出しが出来る public class NamedRectangle extends Rectangle { String name; NamedRectangle() { this("NO NAME"); } } NamedRectangle(String name) { super(56, 78); this.name = name; }
  49. 49. this() • this("NO NAME"); ▫ もう1つのコンストラクタNamedRectangle(String name)を呼び出している • this()を使うとコンストラクタがたくさん定義さ れていても、初期化処理を共通化することが出 来る
  50. 50. 演習1 • 次の機能をもつPlacedRectangleをRectangleの サブクラスとして宣言しなさい。また、 Rectangleは次スライドに定義されている ▫ 位置を表すint型のフィールドx,yを持つ ▫ 3つのコンストラクタを持つ 1. 引数なし 2. 位置付き 3. 位置と大きさ付き ▫ 位置を変更する(設定する)メソッドsetLocation メソッドを持つ
  51. 51. Rectangle.java class Rectangle { int width; int height; public Rectangle() { setSize(0, 0); } Rectangle(int w, int h) { setSize(w, h); } void setSize(int w, int h) { width = w; height = h; } @Override public String toString() { return "[" + width + ", " + height + "]"; } }
  52. 52. 継承とIS-A関係 • サブクラスがスーパークラスの性質を受け継ぐ ▫ 『サブクラスはスーパークラスの一種である』 ▫ 『○○は○○の一種である』→IS-A関係 classA classB classD classC classE
  53. 53. 多重継承 • Javaでは多重継承はサポートしていないが、イ ンタフェースという機能を使って擬似的に多重 継承を実現することが出来る
  54. 54. 合成とHAS-A関係 • NamedRectangleクラスは、String型のフィール ドを持っていた ▫ String型のインスタンスを自分の名前として持っ ていた ▫ インスタンスをフィールドとして持つと、そのイ ンスタンスを自分の物として扱うことが出来る ▫ このような関係をHAS-A関係という
  55. 55. 継承の目的 • 親の財産を受け継ぐことができれば、子供はゼ ロからスタートしなくてもよい • クラスの継承も同じく、ゼロからではなく、既 存のクラスを拡張してプログラミングすれば時 間の効率化、バグ改修を少なくすることが出来 る
  56. 56. オーバーライド • クラスは、スーパークラスのメソッドを継承す るが、新たなメソッドを追加するだけでなく、 継承したフィールドやメソッドを変更すること が出来る。このような変更をメソッドのオー バーライドと言う
  57. 57. メソッドのオーバーライド public class NamedRectangle extends Rectangle { ... @Override void setSize(int width, int height) { ... } }
  58. 58. メソッドのオーバーライド NamedRectangle nr = new NamedRectangle(); // NamedRectangleのインスタンス生成 nr.setSize(56, 78); // NamedRectangleのsetSizeメソッドの呼び 出し 親クラスのsetSizeメソッドは呼び出されない
  59. 59. シグニチャ • メソッドをオーバーライドするには、サブクラ スで『同じメソッド』を宣言する必要がある • 『同じ』とは ▫ メソッドの名前が等しい ▫ 引数列の型が等しい ことを意味する • この『メソッド名と引数列の型』のことをメ ソッドのシグニチャ(signature)と言う • シグニチャとは『署名』という意味
  60. 60. @Override • @から始まるものをアノテーションと言う • 単なるコメントではなく、コンパイラも理解す るコメント • @Overrideの場合は、メソッド名の綴りミスな どによるオーバーライドの失敗をコンパイラが チェックしてくれる
  61. 61. 演習2 • 演習1で作成したPlacedRectangleクラスに以下 のメソッドを追加しなさい ▫ 標準的な文字列表現を返すメソッドtoString  x = 12, y = 34, width = 56, height = 78のとき、 [ (12, 34) [56, 78] ] と表示されるようにすること
  62. 62. コントラクトは変更してはいけない • あるクラスの『フィールドとメソッドが持つ意 味』をコントラクト(契約)という。 • オーバーライドしたメソッドを書き換えること が可能だが、そのフィールドやメソッドの意味 (コントラクト)を変更してはいけない
  63. 63. オーバーライドとオーバーロード • オーバーライドはスーパークラスのメソッドを 変更すること。オーバーライドは『命令を無効 にする』『決定を覆す』という意味。上書き宣 言。 • オーバーロードは同じ名前と異なる引数を持つ メソッドを多数宣言すること。ロードは『負 荷』のこと。1つの名前にたくさんのメソッドと いう荷物を背負わせている
  64. 64. 多態性とオーバーライド • サブクラスのインスタンスは、スーパークラス のインスタンスとしてみなすことが出来る NamedRectangle nr = new NamedRectangle("name"); このとき、変数nrはRectangle型の変数に代入す ることが出来る Rectangle r = nr;
  65. 65. 多態性とオーバーライド • 犬のポチを『犬』としてではなく、『哺乳類』 として扱っている • このように同じインスタンスが、変数nr経由で はNamedRectangleとして扱われ、変数rでは Rectangleとして扱われる • このことをオブジェクト指向の用語では、オブ ジェクトの多態性(ポリモルフィズム)と呼ぶ
  66. 66. 多態性とフィールド nr.name 名前が得られる nr.width 幅が得られる nr.height 高さが得られる r.name コンパイルエラー(Rectangleにname フィールドはない) r.width 幅が得られる r.height 高さが得られる
  67. 67. 多態性とメソッド r.setSize(56, 78); • 通常は、RectangleのsetSizeメソッドが呼び出さ れるが、NamedRectangleクラスにsetSizeメ ソッドがあれば(オーバーライドされていれば)、 NamedRectangleクラスのsetSizeメソッドが 呼び出される • 変数rはRectangle型だが、メソッド呼び出しで 実際に呼び出されるメソッドは、その時代入さ れているインスタンスのクラスによって決まる
  68. 68. finalメソッドはオーバーライドできな い • finalが付いたメソッドはサブクラスにも継承さ れるが、サブクラスでそのfinalメソッドを変更 すること(オーバーライドすること)は出来ない
  69. 69. 継承とアクセス制御 • スーパークラスでprivateと書かれたフィールド やメソッドはサブクラスに継承されない ▫ サブクラスからアクセスすることが出来ない • このように、アクセスを許可したり禁止したり する機構のことをアクセス制御と言う
  70. 70. privateフィールドとprivateメソッド class Rectangle { private int width; private int height; private void internalMethod(int width, int height) { ... } ... } class NamedRectangle extends Rectangle { ... void badMethod() { width = 56; height = 78; System.out.println(height); internalMethod(1, 2); } } // コンパイルエラー // コンパイルエラー // コンパイルエラー // コンパイルエラー
  71. 71. アクセスメソッド • 一般的に、フィールドはprivateにすることが多 い →サブクラスによって不用意に変更される ことを防ぐため • フィールドをprivateにして、外から隠し(情報隠 蔽)、そのフィールドを参照/設定するメソッド のことをアクセスメソッド、またはアクセサと 呼ぶ
  72. 72. アクセスメソッド class Rectangle { private int width; private int height; int getWidth() [ return width; } int getHeight() { return height; } void setSize(int w, int h) { this.width = w; this.height = h; } } class NamedRectangle extends Rectangle { ... void goodMethod() { setSize(56, 78); System.out.println(getHeight()); } }
  73. 73. クラスライブラリとパッケージ • プログラミングに有用なクラスは、Java言語処 理系に数多く用意されている。このクラスの集 まりをクラスライブラリと呼ぶ • 関連のあるクラスのいくつかを1つのグループに まとめることも出来る。まとめられたグループ をパッケージと言う
  74. 74. finalクラスと拡張の禁止 • クラスを宣言するとき、final修飾子を付けるとその クラスの拡張は禁止される final class MyClass { ... } • クラスを拡張すると、セキュリティ上問題がある場 合や、プログラムの整合性が崩れる可能性がある場 合にfinalクラスにする • String、Integer、System、Mathクラスなどの java.langパッケージのクラスはfinalクラス
  75. 75. 抽象クラス • メソッドの名前と引数の方だけが定まっていた、 その本体(実装)がないメソッドのことを抽象メ ソッド(abstractメソッド)という • 抽象メソッドを含んでいるクラスを抽象クラス (abstractクラス)と呼ぶ。 • 抽象クラスはインスタンスを作ることができな い
  76. 76. 抽象クラス abstract class Player { public abstract void play(); public void loop(int n) { for (int i = 0; i < n; i++) { play(); } } }
  77. 77. playメソッドの実装 public class TextPlayer extends Player { String text; public TextPlayer(String text) { this.text = text; } @Override public void play() { System.out.println(text); } public static void main(String[] args) { TextPlayer player = new TextPlayer("こんにちは"); player.loop(3); } }
  78. 78. 抽象クラスはサブクラスに期待する • 抽象クラスは、自分で動作は規定しないけど、 どういうメソッドを宣言しなければならないか をサブクラスに強要する • 抽象クラスをうまく使うとサブクラスのメソッ ド名が揃うため、読みやすいプログラムを書く ことが出来る
  79. 79. Numberクラスの場合 抽象メソッド intValue() longValue() byteValue() doubleValue() ... Object Number Integer Long Byte Double メソッド intValue() longValue() byteValue() doubleValue() ... メソッド intValue() longValue() byteValue() doubleValue() ... メソッド intValue() longValue() byteValue() doubleValue() ... メソッド intValue() longValue() byteValue() doubleValue() ...
  80. 80. 演習3 • PlacedRectangleをRectangleのサブクラスとし てではなく、Rectangle型のインスタンス変数を 持つクラスとして宣言しなさい
  81. 81. 演習4 • 以下のプログラムを実行するとき、どのように表示 されるか考えなさい class A { A() { System.out.println("1:A()"); } A(int x) { System.out.println("2:A(int x)"); } } (続く)
  82. 82. 演習4 public class B extends A { B() { System.out.println("3: B()"); } B(int x) { System.out.println("4: B(int x)"); } B(String s) { super(789); System.out.println("5: B(String s)"); } public static void main(String[] args) { System.out.println("-----"); new A(); System.out.println("-----"); new B(); System.out.println("-----"); new A(123); System.out.println("-----"); new B(456); System.out.println("-----"); new B("test"); System.out.println("-----"); } }
  83. 83. 参考文献 • Java言語 プログラミングレッスン[第3版]下 ▫ 結城浩[著]

×