継承、インターフェイス
ここでは、継承について詳しく説明します。継承はJavaプログラミングにおいてとても重要なトピックです。継承を使えば、あるクラス(スーパークラス)から他のクラス(サブクラス)を派生することができます。自分がほしいと思う機能を新しいクラスに追加することによって、元のクラスよりもカスタマイズされたクラスを作成することができるのです.
サブクラスの作成
次の例は、継承を使ってサブクラスを作成する方法を示しています。ここでは、vehicle(乗り物)という名前のクラスがあり、そのクラスには、乗り物を始動して、Starting…と出力させるためのStartメソッドがあります。
class vehicle{
   public void start(){
      System.out.println("Starting…");
   }
}
乗り物にはさまざまな種類がありますが、ここでは、乗り物クラス(vehicle)を継承して、車クラス(car)を作成していきます。
carをvehicleのサブクラスとして宣言する方法は次のようにextendsキーワードを使います。
class car extends vehicle{

}
class サブクラス名 extends スーパークラス名
という書式になります。
carクラスはvehicleクラスを継承しているので、carクラスはvehicleクラスからstartメソッドも継承します。また、サブクラスであるcarクラス内で、独自のフィールドやメソッドを定義することもできます。この例では、carクラスにdriveという名前のメソッドを追加しています。
class car extends vehicle{
   public void drive(){
      System.out.println("Driving…");
   }
}
このように、サブクラスの中で独自のメソッドを作成することで、carクラスのオブジェクトから、startメソッドとdriveメソッドの両方をよびだして使うことができます。。
public class Lesson21{
   public static void main(String args[]){
      car c = new car();
      c.start();
      c.drive();
   }
}
このプログラムを実行すると次のようになります。
Starting…
Driving…
これが、基本的なサブクラス化の例です。しかし、これ以外にも多くの作業があります。たとえば、スーパークラス内のメソッドと同じ名前のメソッドをサブクラス内で定義するにはどうしたらいいのでしょうか?スーパークラスのコンストラクタにデータを渡すにはどうするのでしょうか?これらについては後ほど説明していきます。
 スーパークラスのコンストラクタ
スーパークラスからサブクラスを作成することができることは、前のLessonで説明しましたが、スーパークラスにコンストラクタが存在する場合はどうなるのでしょうか?ここではスーパークラスのコンストラクタの呼び出しについて説明していきます。

aというクラスがあり、このクラスにはパラメータ引数を受け取らないコンストラクタがあるとします。
class a{
   a(){
      System.out.println("クラスaのコンストラクタを呼び出しています。");
   }
}
その後、クラスaからクラスbをサブクラス化します。
class b extends a{

}
クラスbのオブジェクトを作成すると、クラスaの中のコンストラクタが自動的に呼び出されます。
class Lesson21{
   public static void main(String args[]){
      b obj = new b();
   }
}
このプログラムを実行すると次のようになります。
クラスaのコンストラクタを呼び出しています。
次に、クラスbにパラメータをとらないコンストラクタを追加したとします。
class a{
   a(){
      System.out.println("クラスaのコンストラクタを呼び出しています。");
   }
}

class b{
   b(){
      System.out.println("クラスbのコンストラクタを呼び出しています。");
   }
}

public class Lesson21{
   public static void main(String args[]){
      b obj = new b();
   }
}
この場合、クラスbのオブジェクトを作成すると、クラスaとクラスbの両方のコンストラクタが呼び出されます。コンストラクタが呼び出される順序としては、親クラスのほうが先になります。
クラスaのコンストラクタを呼び出しています。
クラスbのコンストラクタを呼び出しています。
次に、クラスbのコンストラクタがパラメータを1つ受けるように修正を加えたとします。
class a{
   a(){
      System.out.println("クラスaのコンストラクタを呼び出しています。");
   }
}

class b{
   b(String s){
      System.out.println("クラスbのコンストラクタを呼び出しています。");
      System.out.println(s);
   }
}

public class Lesson21{
   public static void main(String args[]){
      b obj = new b("abcdefg...");
   }
}
この場合は、クラスaのコンストラクタとクラスbのコンストラクタが呼び出されます。
クラスaのコンストラクタを呼び出しています。
クラスbのコンストラクタを呼び出しています。
abcdefg...
パラメータを受け取らないコンストラクタは、クラスのデフォルトコンストラクタと呼ばれます。このコンストラクタは、クラスのサブクラスをインスタンス化するときに、特にパラメータを指定しなければ、自動的にJavaによって呼び出されます。
次に、クラスaに文字列を処理するコンストラクタを追加しましょう。
class a{
   a(){
      System.out.println("クラスaのコンストラクタを呼び出しています。");
   }

   a(String s){
      System.out.println("クラスaのコンストラクタを呼び出しています。");
      System.out.println(s);
   }
}
そして、クラスaの中で、デフォルトのコンストラクタではなく、Stringパラメータを受け取るコンストラクタを呼び出したいとします。このためには、クラスbのコンストラクタ内で、次のようにしてsuperメソッドを呼び出します。
class a{
   a(){
      System.out.println("クラスaのコンストラクタを呼び出しています。");
   }

   a(String s){
      System.out.println("クラスaのコンストラクタを呼び出しています。");
      System.out.println(s);
   }
}

class b extends a{
   b(String s){
      super(s);
      System.out.println("クラスbのコンストラクタを呼び出しています。");
      System.out.println(s);
   }
}

public class Lesson21{
   public static void main(String args[]){
      b obj = new b("abcdefg...");
   }
}
これでクラスbのオブジェクトをインスタンス化すると、クラスaのデフォルトコンストラクタではなく、Stringパラメータを受け取るメソッドが呼び出されます。
クラスaのコンストラクタを呼び出しています。
abcdefg...
クラスbのコンストラクタを呼び出しています。
abcdefg...
superメソッドを使ってスーパークラスのコンストラクタを呼び出す場合は、その行をコンストラクタ内の最初の行に記述しなければなりません。
メソッドのオーバーライド 
スーパークラスから継承したメソッドをオーバーライドすることもできます。これは、新しいバージョンのメソッドで置き換えるということです。
次の例はメソッドのオーバーライドを使ったアプリケーションです。継承階層を形成する2つのクラスを使います。各クラスでは、同じ名前で、同じ引数を持つhelloメソッドを宣言します。つまり、サブクラスのhelloメソッドはスーパークラスのhelloメソッドをオーバーライドしています。
class a1{
   void hello(){
      System.out.println("Hello from class a1");
   }
}
その後、クラスa1からクラスb1をサブクラス化します。
class b1 extends a1{
   void hello(){
      System.out.println("Hello from class b1");
   }
}
クラスbのオブジェクトを作成すると、helloメソッドを呼び出します。するとb1で定義したhelloメソッドが呼び出されます。。
class Lesson22{
   public static void main(String args[]){
      b1 obj = new b1();
      obj.hello();
   }
}
このプログラムを実行すると次のようになります。
Hello from class b1
このように、継承階層において、メソッドのオーバーロードを用いることによって、スーパークラスのメソッドを隠すことができます。しかし、スーパークラスで定義された元のメソッドを使う場合にはどうすればいいのでしょうか?
Javaにはこの機能は備わっています。スーパークラスのメソッドを参照するには、superキーワードを使います。
super.スーパークラスのメソッド名(引数)
という書式で使います。
class b1 extends a1{
   void hello(){
      super.hello();
      System.out.println(Hello from class b1);
   }
}
として、Lesson21のアプリケーションを実行すると次のようになります。
Hello from class a1
Hello from class b1
クラスの修飾子 
classキーワードの前に指定できる修飾子は3つあります。その機能を簡単にまとめると次のようになります。
キーワード 意味
abstract インスタンス化できないクラス
final 拡張できない(継承できない)クラス
public ほかのすべてのクラスから参照できるクラス。
クラスを作成する際には、前もって汎用的なコードだけを用意して、カスタマイズはそのクラスをサブクラス化する開発者に任せるということがあります。開発者にコードをカスタマイズさせるためには、メソッドを抽象化します。こうすると、開発者がメソッドをオーバーライドしなければ、そのメソッドを使うことができなくなります。抽象メソッドを作成するにはabstractキーワードを使います。クラス内のメソッドを抽象化したい場合は、クラスそのものを抽象化しなければなりません。
次に例を示します。この例では、aという名前のクラスを作成します。このクラスは文字列を出力するprintメソッドを持っていて、getDataというメソッドを呼び出すことによって出力する文字列を取得します。
class a{
   String getData();

   public void print(){
      System.out.println(getData());
   }
}
出力するデータの内容は、開発者に指定させるので、getDataメソッドには中身がありません。getDataメソッドの中身を記述しなければならないことを開発者に知らせるために、メソッドを抽象化します。クラスそのものも抽象化する必要があります。
abstract class a{
   abstract String getData();

   public void print(){
      System.out.println(getData());
   }
}
これで、aをサブクラス化する際には、getDataメソッドの中身を書かなければなりません。次に例を示します。
class b{
   String getData(){
      return "こんにちわ";
   }
}
次に、このサブクラスの使用例を示します。
class Lesson 22{
   public static void main(String args[]){
      b b1 = new b();
      b1.print();
   }
}
次に、このアプリケーションの実行結果を示します。
こんにちわ
 インターフェイス
インターフェイスとは、クラス形式を定義する定数とメソッドの宣言を集めたものです。ただし、インターフェイスにメソッドの中身は記述しません。基本的にインターフェイスとは、クラスの役割を果たすもので、その具体的な方法を決めるものではありません。ほかのクラスを作成して、そこにインターフェイスの中身を記述することができます。
インターフェイスの宣言は基本的に次のような形式です。
修飾子 interface インターフェイス名{
   定数の宣言;
   メソッドの宣言;

(注意)インターフェイスでは、変数には値を代入して定数にしておかなければなりません。
クラスには、1つまたは複数のインターフェイスを実装することができます。インターフェイスを実装するには、まずクラス定義で、implementsキーワードを使って、実装対象のインターフェイスを指定します。次に、インターフェイスで指定されているメソッドをクラスにすべて実装します。implementsキーワードの構文は次のとおりです。
修飾子 class クラス名 extends スーパークラス名 implements インターフェイス名
  インターフェイスのメソッドの実装

クラスにインターフェイスを実装する場合、そのインターフェイスで宣言されているメソッドをすべて実装しなければなりません。

つぎに例を示します。
この例では、printTextというメソッドをもつPrintemというインターフェイスを作成し、このインターフェイスをclass1という名前のクラスで実装します。
interface Printem{
   void printText();
}
次にこのインターフェイスをclass1で実装します。
interface Printem{
   void printText();
}

public class Lesson23{
   public static void main(String args[]){
      class1 obj = new class1();
      obj.printText();
   }
}

class class1 implements Printem{
   public void printText(){
      System.out.println("こんにちわ");
   }
}
このプログラムを実行すると次のようになります。
こんにちわ
また、インターフェイスを部分的に実装するようなクラスを作成することができます。ただし、そのようなクラスはabstract宣言する必要があります。というのも、これらのクラスは部分実装でしかなく、オブジェクトとしてインスタンス化することができないからです。
次に例を示します。この例では、printText1とprintText2という2つのメソッドを持つインターフェイスを作成しています。
interface Printem{
   void printText1();
   void printText2();
}
次に、このインターフェイスを実装する新しいクラスとして、class1を作成します。このクラスでは、printText2メソッドだけを実装します。(class1はこのインターフェイスの完全実装ではないので、abstractとして宣言しなければなりません。)
interface Printem{
   void printText1();
   void printText2();
}

abstract class class1 implements Printem{
   public void printText1(){
      System.out.println("こんにちわ");
   }
}
さらに、class1を拡張した新しいクラスとして、class2を作成し、printText2メソッドを実装します。つまり、class2のオブジェクトをインスタンス化できるのです。
interface Printem{
   void printText1();
   void printText2();
}

abstract class class1 implements Printem{
   public void printText1(){
      System.out.println("こんにちわ");
   }
}

class class2 extends class1{
   public void printText2(){
      System.out.println("こんばんわ");
   }
}

public class Lesson24{
   public static void main(String args[]){
      class2 obj = new class2();
      obj.printText2();
   }
}
このアプリケーションを実行すると、次のようになります。
こんばんわ
このような、インターフェイスの部分実装は、インターフェイスの一部のメソッドについて、一群のサブクラスでどのように動作するか指定するときなどに便利です。