この章で行う学習内容
●作成したクラスを使ってさらに拡張することが出来る継承について
●独自の例外を作成する自作例外について
●クラスのキャストについて
●メソッドの処理を定義しない抽象について
●クラスによく似たインタフェースについて
●独自の例外を作成する自作例外について
●クラスのキャストについて
●メソッドの処理を定義しない抽象について
●クラスによく似たインタフェースについて
継承
継承とは
継承するとはどういうことか、簡単にいうと性質を受け継ぐということです。
人間でいうと、人間は動物の性質を受け継いでいます。(継承している)
つまり、人間という概念(クラス)は動物という概念(クラス)を継承しています。
同様に、犬や猫なども動物という概念(クラス)を継承しています。
動物
●人間 ●犬 ●ネコ 『継承している』
このように、性質を受け継がれる側(継承される側)をスーパークラス
または親クラスといい、性質を受け継ぐ側(継承する側)をサブクラス
または、子クラスといいます。
人間でいうと、人間は動物の性質を受け継いでいます。(継承している)
つまり、人間という概念(クラス)は動物という概念(クラス)を継承しています。
同様に、犬や猫なども動物という概念(クラス)を継承しています。
動物
●人間 ●犬 ●ネコ 『継承している』
このように、性質を受け継がれる側(継承される側)をスーパークラス
または親クラスといい、性質を受け継ぐ側(継承する側)をサブクラス
または、子クラスといいます。
Javaにおける継承とは
クラスには、メンバ(フィールド、メソッド)があります。継承するということは、
このクラスのメンバを受け継ぐということになります。
利点
①サブクラスではスーパークラスで定義したメンバを再度定義しなくても使うことができる。
②共通処理に修正が入った場合に、スーパークラスだけ修正すれば、サブクラスの処理は修正しなくてもよい。
③スーパークラスを継承してサブクラスを作成する場合、スーパークラスの機能を引き継いだまま、 サブクラスでは、さらに機能を追加することが出来る。
継承のルール
①スーパークラスのprivete修飾子がついているメンバは継承されない。
②サブクラスはいくつでも作ることが出来るが、継承出来るスーパークラスは1つだけ。
③継承には、必ず「 is a 関係 」が成立しなければならない。(~は~である)
このクラスのメンバを受け継ぐということになります。
利点
①サブクラスではスーパークラスで定義したメンバを再度定義しなくても使うことができる。
②共通処理に修正が入った場合に、スーパークラスだけ修正すれば、サブクラスの処理は修正しなくてもよい。
③スーパークラスを継承してサブクラスを作成する場合、スーパークラスの機能を引き継いだまま、 サブクラスでは、さらに機能を追加することが出来る。
継承のルール
①スーパークラスのprivete修飾子がついているメンバは継承されない。
②サブクラスはいくつでも作ることが出来るが、継承出来るスーパークラスは1つだけ。
③継承には、必ず「 is a 関係 」が成立しなければならない。(~は~である)
構文
public class 新しく作成するクラス名 (サブクラスのクラス名) extends 継承するクラス名 (スーパークラスのクラス名){ }
例えば、車。
車といえば、ハンドルがあって、ブレーキがあって、アクセルが…という感じになります。
この車を継承してタクシーを作成してみます。
まず、「 is a 関係 」かどうかを確認します。「タクシーは車である」と、言う事が出来ます。
なので、タクシーは車を継承出来ます。
タクシーには車の機能以外に追加されている機能があります。
それは、料金メーターや屋根についているものです。
もし、タクシーを1から作成しようとすると、車の機能も全て定義しなければなりません。
しかし、車を継承しているので、車の基本的な機能は既に定義されています。
あとは、タクシー独自の機能を定義するだけでタクシーを完成することが出来てしまい
ます。
同じように、トラックなども車クラスを継承して独自の機能を追加してやればよいことになります。
車といえば、ハンドルがあって、ブレーキがあって、アクセルが…という感じになります。
この車を継承してタクシーを作成してみます。
まず、「 is a 関係 」かどうかを確認します。「タクシーは車である」と、言う事が出来ます。
なので、タクシーは車を継承出来ます。
タクシーには車の機能以外に追加されている機能があります。
それは、料金メーターや屋根についているものです。
もし、タクシーを1から作成しようとすると、車の機能も全て定義しなければなりません。
しかし、車を継承しているので、車の基本的な機能は既に定義されています。
あとは、タクシー独自の機能を定義するだけでタクシーを完成することが出来てしまい
ます。
同じように、トラックなども車クラスを継承して独自の機能を追加してやればよいことになります。
例文(継承)
スーパークラス
public class Car { String carName; public void move(){ System.out.println(“動きます”); } public void stop(){ System.out.println(“とまります”); } }
Mainクラス
public class KeisyoSample{ public static void main(String[] args) { Taxi tax = new Taxi(); tax.move(); tax.chargeMeter(); tax.stop(); } }
サブクラス
public class Taxi extends Car{ public void chargeMeter{ System.out.println(“料金が上がります”); } }
実行結果
動きます 料金が上がります とまります
例文(継承と変数)1
Javaの継承ではフィールドも継承されます。
しかし、スーパークラスとサブクラスで同じ変数名があった場合はどちらが優先されるのでしょう?
それは、サブクラスの変数が優先されます。
しかし、スーパークラスとサブクラスで同じ変数名があった場合はどちらが優先されるのでしょう?
それは、サブクラスの変数が優先されます。
スーパークラス
public class Car { String carName=“スーパーカー”; }
Mainクラス
public class KeisyoSample{ public static void main(String[] args) { Taxi tax = new Taxi(); tax.move(); System.out.println(tax.carName); } }
サブクラス
public class Taxi extends Car{ String carName=“サブカー”; }
実行結果
サブカー
例文(継承と変数)2
スーパークラスの変数は参照することは出来ないのでしょうか?
そんなことはありません。以下のように記述すれば、スーパークラスの変数も参照することができます。
そんなことはありません。以下のように記述すれば、スーパークラスの変数も参照することができます。
構文
スーパークラスの変数参照 super.変数名
スーパークラス
public class Car { String carName=“スーパーカー”; }
Mainクラス
public class KeisyoSample{ public static void main(String[] args) { Taxi tax = new Taxi(); tax.move(); tax.superShow(); tax.subShow(); } }
サブクラス
public class Taxi extends Car{ String carName=“サブカー”; public void superShow(){ System.out.println( super.carName ); } public void subShow(){ } }
実行結果
スーパーカー サブカー
継承とメソッド
同じ名前のメソッドがあった場合どうなるでしょう?
変数と同じようにサブクラスのメソッドが優先されます。
これは、スーパークラスで定義されているメソッドをサブクラスで再定義
するということになります。
この再定義を「オーバーライド」と言います。
スーパークラスにメソッドはあるが、サブクラスなりの処理をしたい場合
にオーバーライドします。
オーバーライドのルール
①メソッド名、戻り値の型、引数の数と型が全て同じで、中の処理をかえるだけである。
②メソッドの機能(概要)は同じでなければならない。
③スーパークラスのメソッドを再定義することである。
変数と同じようにサブクラスのメソッドが優先されます。
これは、スーパークラスで定義されているメソッドをサブクラスで再定義
するということになります。
この再定義を「オーバーライド」と言います。
スーパークラスにメソッドはあるが、サブクラスなりの処理をしたい場合
にオーバーライドします。
オーバーライドのルール
①メソッド名、戻り値の型、引数の数と型が全て同じで、中の処理をかえるだけである。
②メソッドの機能(概要)は同じでなければならない。
③スーパークラスのメソッドを再定義することである。
例文(継承とメソッド)1
スーパークラス
public class Car { String carName=“スーパーカー”; public void move() { System.out.println(carName + “は動きだしました”); } }
Mainクラス
public class Taxi extends Car{ String carName=“サブカー”; public void move(){ System.out.println( carName + “は荷物を積んで動きだしました。” ); } }
サブクラス
public class KeisyoSample{ public static void main(String[] args) { Taxi tax = new Taxi(); System.out.println(trac.move()); } }
実行結果
サブカーは荷物を積んで動き出しました。
例文(継承とメソッド)2
メソッドもスーパークラスのメソッドを呼ぶ出すことができます。その際にもsuperを使用します。
スーパークラス
スーパークラス
public class Car { String carName=“スーパーカー”; public void move() { System.out.println(carName + “は動きだしました”); } }
Mainクラス
public class Track extends Car{ String carName=“サブカー”; public void move(){ super.move(); System.out.println( carName + “は荷物を積んで動きだしました。” ); } }
サブクラス
public class KeisyoSample{ public static void main(String[] args) { Track trac = new Track(); trac.move(); } }
実行結果
スーパーカーは動き出しました
サブカーは荷物を積んで動き出しました。
例文(継承とメソッド)3
フィールドとメソッドはスーパークラスから引き継がれましたが、
コンストラクタはどうなるでしょう?
継承を行ってもコンストラクタは継承されません。
スーパークラス
コンストラクタはどうなるでしょう?
継承を行ってもコンストラクタは継承されません。
スーパークラス
public class Car { int a; int b; public Car () { a = 10; b = 100; } }
Mainクラス
public class KeisyoSample{ public static void main(String[] args) { Taxi tax = new Taxi(); System.out.println( “a :” + tax.a ); System.out.println( “b :” + tax.b ); } }
サブクラス
public class Taxi extends Car{ public Taxi (){ b = 200; } }
実行結果
a :10 b :200
まずスーパークラスのコンストラクタが実行され、次にサブクラスのコンストラクタ
が実行されます。 順番も、スーパークラス ⇒ サブクラスの順番です。
それでは、コンストラクタについては次節で確認していきましょう。
継承とコンストラクタ
コンストラクタに何も指定しない場合は、
引数のないデフォルトコンストラクタが自動的に実行されるという性質がありました。
継承をした場合でも同じ性質があります。
何も指定しない場合は、スーパークラスのコンストラクタが自動的に実行され、
その後にサブクラスのコンストラクタが実行されます。
サブクラス
引数のないデフォルトコンストラクタが自動的に実行されるという性質がありました。
継承をした場合でも同じ性質があります。
何も指定しない場合は、スーパークラスのコンストラクタが自動的に実行され、
その後にサブクラスのコンストラクタが実行されます。
サブクラス
public class Taxi extends Car{ public Taxi (){ b = 200; } }
何も記述されていませんが、ここで、スーパークラスのコンストラクタが自動的に 実行されている。
明示的なコンストラクタ
デフォルトコンストラクタ以外のコンストラクタを使用する場合は、
自動的に実行されるのを待つというわけにはいきません。
そこで、サブクラスのコンストラクタからスーパークラスのコンストラクタを
明示的に呼び出せるようになっています。
明示的なコンストラクタ
デフォルトコンストラクタ以外のコンストラクタを使用する場合は、
自動的に実行されるのを待つというわけにはいきません。
そこで、サブクラスのコンストラクタからスーパークラスのコンストラクタを
明示的に呼び出せるようになっています。
構文
スーパークラスのコンストラクタ呼び出し super( 引数 );
コンストラクタでのsuperの注意点
①指定方法がsuper( 引数 )だけで特に名前等は指定しません。
②サブクラスのコンストラクタの一番最初に記述しなければならない。
③コンストラクタの呼び出しはコンストラクタでしか実施できない。
①指定方法がsuper( 引数 )だけで特に名前等は指定しません。
②サブクラスのコンストラクタの一番最初に記述しなければならない。
③コンストラクタの呼び出しはコンストラクタでしか実施できない。
例文(継承とコンストラクタ)1
フィールドとメソッドはスーパークラスから引き継がれましたが、
コンストラクタはどうなるでしょう?
継承を行ってもコンストラクタは継承されません。
スーパークラス
コンストラクタはどうなるでしょう?
継承を行ってもコンストラクタは継承されません。
スーパークラス
public class Car { String carName; String color; public Car () { } public Car (String str) { carName = “スーパーカー”; color = str; } public Car (String str, String str2) { carName = str; color = str2; } }
Mainクラス
public class KeisyoSample{ public static void main(String[] args) { Taxi tax1 = new Taxi(); Taxi tax2 = new Taxi(“黄色”); System.out.println( “a :” + tax1.carName ); System.out.println( “b :” + tax1.color ); System.out.println( “a :” + tax2.carName ); System.out.println( “b :” + tax2.color ); } }
サブクラス
public class Taxi extends Car{ public Taxi (){ super(“赤”); } public Taxi (String str){ super(“タクシー”, str); } }
実行結果
a :スーパーカー b :赤 a :タクシー b :黄色
継承とObjectクラス
Javaでは、様々なクラスがありますが、それらは継承関係で結ばれています。 では、その継承関係の一番上にあるスーパークラスになるものはなんでしょう? それは「Objectクラス」です。Objectクラスはクラスの頂点に位置しているもので、 全てのクラスにはこのObjectクラスが必ず継承されます。 extendsを使用せずに自分で作成したプログラムも何も継承されていないように見えますが、 実は、Objectクラスを継承しているのです。 extendsを記述しない場合は、Objectクラスがデフォルトで継承されるというJavaのルールがあるのです。 その為、全てのクラスはObjectクラスで定義されている変数やメソッドを持っていることになります。
「java.lang.object」と記載されている通り、
stringクラスは、objectクラスを
継承していることになります。
自分で作成したjavadocを見てみてください。
同じようにobjectクラスを継承しています。
stringクラスは、objectクラスを
継承していることになります。
自分で作成したjavadocを見てみてください。
同じようにobjectクラスを継承しています。
補足 アクセス修飾子
アクセス修飾子としてpublic、private以外に「protected」という修飾子があります。
これは、同一パッケージ内、又は継承関係にあるクラスであれば、
参照可能という意味の修飾子です。
アクセス修飾子一覧
アクセス修飾子一覧
宣言子 | 他クラスからのアクセス | サブクラスからのアクセス |
---|---|---|
public | 可 | 可 |
protected | 同一パッケージから可 | 可 |
宣言なし | 同一パッケージから可 | 不可 |
private | 不可 | 不可 |
自作例外
自作例外とは
自分で独自に作成した例外のことです。
利点
①javaが提供していないアプリケーション独自の例外を作成することが出来る。
②例外の種類を増やすことで、例外を細かく定義出来る。
注意点
exceptionの生成時には2パターンある。
①メッセージなし
new exception();
②メッセージあり new exception(“エラーです。”);
つまりコンストラクタを絶対に2つ生成しなければならないということになる。
作成方法
exceptionクラスを継承する。
☆通常javaが提供しているioexceptionなども同じように
継承して作成されている。
利点
①javaが提供していないアプリケーション独自の例外を作成することが出来る。
②例外の種類を増やすことで、例外を細かく定義出来る。
注意点
exceptionの生成時には2パターンある。
①メッセージなし
new exception();
②メッセージあり new exception(“エラーです。”);
つまりコンストラクタを絶対に2つ生成しなければならないということになる。
作成方法
exceptionクラスを継承する。
☆通常javaが提供しているioexceptionなども同じように
継承して作成されている。
自作例外のルール
例外の階層は下記のようなっています。
・error・・・システムの致命的なエラー
・exception・・・一般的な例外
・runtimeexception・・・実行時に発生する例外で、
処理を必要としないもの。
一般的には致命的なエラー(処理を継続しない)として扱われます。
独自の例外を作成する場合は、このexceptionを継承
して例外を作成します。
catchを記述する順番も決まっています。
「階層の下にあるものから先にcatchしていく。」
階層が上のものは下の例外もcatch出来てしまう為、
下から順番にcatchしていかなければならないのです。
(通常のapiでも同様です。)
・error・・・システムの致命的なエラー
・exception・・・一般的な例外
・runtimeexception・・・実行時に発生する例外で、
処理を必要としないもの。
一般的には致命的なエラー(処理を継続しない)として扱われます。
独自の例外を作成する場合は、このexceptionを継承
して例外を作成します。
catchを記述する順番も決まっています。
「階層の下にあるものから先にcatchしていく。」
階層が上のものは下の例外もcatch出来てしまう為、
下から順番にcatchしていかなければならないのです。
(通常のapiでも同様です。)
例文
public class MyException extends Exception { // メッセージなし public MyException() { super(); } // メッセージ有り public MyException( String msg ) { super(“独自エラー :” + msg ); } }
public class Test { public int minus( int a, int b ) throws MyException { int c = a -b; if ( c < 0 ) { // 自作例外をthrowする throw new MyException( "結果がマイナスです。" ); } return c; } }
public class ExceptionSample { public static void main ( String[] args ) { try{ int a = Integer.parseInt( args[0] ); int b = Integer.parseInt( args[1] ); Test test = new Test(); test.minus( a ,b ); }catch(Exception e){ e. printStackTrace(); } } }
実行結果
>java ExceptionSample 3 5 MyException : 独自エラー : 結果がマイナスです。 at Test.minus(Test.java7) at Main.main(Main.java12)
クラスキャスト
クラスキャストとは
クラスキャストとは
クラスの型変換のことです。
キャストの条件
キャストする場合は、必ず継承関係でなければならない。
全てのクラスはobject型にキャストすることが出来る)
キャストの種類
キャストには暗黙キャストと明示キャストの2種類がある。
暗黙キャスト
サブクラスからスーパークラスにキャストを行うこと。
クラスの型変換のことです。
キャストの条件
キャストする場合は、必ず継承関係でなければならない。
全てのクラスはobject型にキャストすることが出来る)
キャストの種類
キャストには暗黙キャストと明示キャストの2種類がある。
暗黙キャスト
サブクラスからスーパークラスにキャストを行うこと。
構文
犬 a = new 犬(); 動物 b = a;
明示キャスト
スーパークラスからサブクラスにキャストすること。
明示キャストの注意点
元々サブクラスのインスタンスではないものは、キャスト出来ない。
なので、暗黙キャストしたオブジェクトを元の型に戻すときに使用する。
明示キャストの注意点
元々サブクラスのインスタンスではないものは、キャスト出来ない。
なので、暗黙キャストしたオブジェクトを元の型に戻すときに使用する。
構文
猫 a = new 猫(); 動物 b = a; 犬 c = (犬)b;
bの動物は元々犬ではないので、最後のキャスト出来ない。
構文
犬 a = new 犬(); 動物 b = a; 犬 c = (犬)b; ↑↑↑↑↑↑↑↑↑↑ ☆()の中に明示的にキャストする型を指定する。
犬を犬に戻しただけなので、キャスト出来る。
キャスト時の注意点
使用できる機能(フィールド、メソッド)は、キャスト時のクラスで定義されている物のみです。
犬から動物へキャストするということは、「犬」という型が「動物」という型にくるまれる状態になっています。 その為、犬特有のフィールド、メソッドは見えなくなり、使えなくなってしまいます。
つまり、動物 a = new 犬(); という宣言の場合、犬クラスのフィールド、メソッドは見ることが出来ず、 動物クラスのフィールド、メソッドしか参照、呼び出しを行うことが出来ないということです。
犬から動物へキャストするということは、「犬」という型が「動物」という型にくるまれる状態になっています。 その為、犬特有のフィールド、メソッドは見えなくなり、使えなくなってしまいます。
つまり、動物 a = new 犬(); という宣言の場合、犬クラスのフィールド、メソッドは見ることが出来ず、 動物クラスのフィールド、メソッドしか参照、呼び出しを行うことが出来ないということです。
抽象クラス
抽象クラスとは
抽象クラスとは
抽象メソッドを持っているクラスのことです。
抽象メソッドとは
クラス内でそのメソッドが存在することは確定しているが、
まだ処理が確定していない場合に抽象メソッドにします。
抽象メソッドはそのクラスを継承したサブクラスが必ず
オーバーライドしなければなりません。
その為、サブクラス側で処理を確定するメソッドになります。
修飾子
抽象を表す修飾子が存在しています。
それは、「 abstract 」です。これが付いたクラスやメソッドは抽象になります。
注意点
①抽象クラスのインスタンスは生成出来ません。
②抽象メソッドには処理を定義しません。
③サブクラスが抽象メソッドをオーバーライドしないと、コンパイルエラーになります。
④抽象クラスでは、抽象メソッド以外の通常のメソッドも定義できます。
抽象メソッドを持っているクラスのことです。
抽象メソッドとは
クラス内でそのメソッドが存在することは確定しているが、
まだ処理が確定していない場合に抽象メソッドにします。
抽象メソッドはそのクラスを継承したサブクラスが必ず
オーバーライドしなければなりません。
その為、サブクラス側で処理を確定するメソッドになります。
修飾子
抽象を表す修飾子が存在しています。
それは、「 abstract 」です。これが付いたクラスやメソッドは抽象になります。
注意点
①抽象クラスのインスタンスは生成出来ません。
②抽象メソッドには処理を定義しません。
③サブクラスが抽象メソッドをオーバーライドしないと、コンパイルエラーになります。
④抽象クラスでは、抽象メソッド以外の通常のメソッドも定義できます。
例文(抽象クラス)1
スーパークラス
abstract public class Animal { // 戦う public void battel() { this.thread(); this.attack(); } // 威嚇 abstract public void thread(); // 攻撃 abstract public void attack(); } // ☆メソッドですが、{ } ではなく、処理が無い為、 // ;(セミコロン)で終わります。
サブクラス
public class Dog extends Animal { // 威嚇 public void thread() { System.out.println( "ウゥゥゥ!!" ); } // 攻撃 public void attack() { System.out.println( "かみ付き!!" ); } }
インタフェース
インタフェースとは
継承関係にないクラスに、機能(振る舞い)を提供するものです。
例) 例えば、タクシーは車と継承関係ですが、このタクシーについている
機能の「走る」は継承関係ではありません。車はもちろん走ることが
出来ますが、人間も走ることが出来ます。
同じように動物も走ることが出来ます。
又は、「ドア」や「乗る」なども同じことが言えます。
このように継承とは関係が無く、何かに依存はしないが、
必要な機能をインタフェースとして定義します。
インタフェースのルール
①メソッドは全て抽象メソッドとなる。
その為、処理を記載することは出来ない。
②フィールドは全て定数になる。
③多重実装することが出来る。
④抽象メソッドしかメソッドは定義出来ないのでインスタンスは生成できない。
例) 例えば、タクシーは車と継承関係ですが、このタクシーについている
機能の「走る」は継承関係ではありません。車はもちろん走ることが
出来ますが、人間も走ることが出来ます。
同じように動物も走ることが出来ます。
又は、「ドア」や「乗る」なども同じことが言えます。
このように継承とは関係が無く、何かに依存はしないが、
必要な機能をインタフェースとして定義します。
インタフェースのルール
①メソッドは全て抽象メソッドとなる。
その為、処理を記載することは出来ない。
②フィールドは全て定数になる。
③多重実装することが出来る。
④抽象メソッドしかメソッドは定義出来ないのでインスタンスは生成できない。
構文
interface・・・classではなく、interfaceを使って定義します。 implements・・・インタフェースを実装(≒継承)する時に使う。
interface インタフェース名 { int a = 5; void execute(); }
public class 実装するクラス名 implements インタフェース名 { void execute() { // 処理 } }
例文
interface Exe { void open(); void close(); }
public class Book implements Exe { public void open() { System.out.println( "本が開いた" ); } public void close() { System.out.println( "本が閉じた" ); } }
public class Pot implements Exe { public void open() { System.out.println( "ふたが開いた" ); } public void close() { System.out.println( "ふたが閉じた" ); } }