第8回Java勉強会 †
概要 †
抽象クラス †
インターフェース †
多態性 †
詳細 †
抽象クラス †
abstractとは「抽象的な」といった意味になります。
つまりabstractなクラスといったら抽象的なクラスといった意味になります。
抽象クラスとは、自分で処理は記述しないけど、どういった処理を記述しなければなりせんよという抽象メソッドを持ちます。
それを実装するサブクラスに処理内容の要請するクラスのことを言います。
- abstractクラスの特徴
- クラス定義にabstractと付く
- abstractクラスは継承されるためにある
- サブクラスに実装してもらいたいメソッド(抽象メソッド)を持つ
- abstractクラスは抽象的なものなのでインスタンス化ができません。
abstract クラス名 {
abstract 戻り値の型 メソッド名();
}
- abstractクラスを作る意味
抽象クラスによって、abstractメソッドを実装しなければならないという制約をつくることで
その抽象クラスを継承したクラス達は同じメソッドを持つことになり、それぞれのサブクラスの
見た目をある程度そろえることができるというクラス設計の方法である。
- 抽象クラスを実装するサンプルです。
ファイル名:Calculation.java
public abstract class Calculation {
double x;
double y;
public Calculation(){
this.x = 0;
this.y = 0;
}
public Calculation(double x, double y){
this.x = x;
this.y = y;
}
public abstract double calculate();
public void method(){
System.out.println("抽象クラスに書かれている処理です");
}
}
ファイル名:Addition.java
public class Addition extends Calculation {
public Addition() {
super();
}
public Addition(double x, double y) {
super(x,y);
}
public double calculate() {
return (this.x + this.y);
}
}
抽象クラスを実装したクラスの動作を確認します。
ファイル名:AbstractTest?.java
public class AbstractTest {
public static void main(String[] args) {
Addition add = new Addition(10, 10);
System.out.println("addの実行結果=" + add.calculate());
}
}
インターフェース †
- インターフェースの持つフィールドは定数となります。(public static final)
- インターフェースのメソッドは全て抽象メソッドとなります。
- インターフェースはインスタンス化できません。
- 実装クラス(implementsするクラス)では複数のインターフェースを指定することができます
- インターフェースの定義方法
- インターフェースの実装方法
class クラス名 implements インターフェース名 {
}
- 図形のインターフェースを定義しましす。
ファイル名:Diagram.java
public interface Diagram {
double getArea();
}
ファイル名:Rectangle.java
public class Rectangle implements Diagram{
double width;
double height;
public Rectangle(){
this.width = 0;
this.height = 0;
}
public Rectangle(double width, double height){
this.width = width;
this.height = height;
}
public double getArea(){
return (this.width * this.height);
}
}
ファイル名:InterfaceTest?.java
public class InterfaceTest {
public static void main(String[] args) {
Rectangle rectangle = new Rectangle(10, 20);
System.out.println("rectangleの面積=" + rectangle.getArea());
}
}
抽象クラスとインターフェース †
抽象クラスとインターフェースの違いは以下のようになります。
| 抽象クラス | インターフェース |
| 処理のあるメソッドを書くことができる | 抽象メソッドしか書くことはできない |
| フィールドは自由に設定できる | 定数しか書くことができない |
| extends(継承)して実装をする | implementsして実装する |
多態性 †
継承関係やインターフェースの実装などで共通の共通のメソッドを持つクラスはスーパークラスまたは、インターフェースの変数として同じメソッドを呼び出したとしても、それぞれ異なった処理(違う振る舞い)を行うことができます。
- 抽象クラスを使用した例
ファイル名:Calculation.java(上記サンプルコードをそのまま使用します)
ファイル名:Addition.java(上記サンプルコードをそのまま使用します)
新たに掛け算ようのクラスを作成します。
ファイル名:Multiplication.java
public class Multiplication extends Calculation {
public Multiplication() {
super();
}
public Multiplication(double x, double y) {
super(x,y);
}
public double calculate() {
return (this.x * this.y);
}
}
ファイル名:AbstractTest?.java
public class AbstractTest {
public static void main(String[] args) {
Calculation calc1 = new Addition(10, 10);
Calculation calc2 = new Multiplication(10, 10);
System.out.println("calc1の実行結果=" + calc1.calculate());
System.out.println("calc2の実行結果=" + calc2.calculate());
}
}
- インターフェースを利用した例
ファイル名:Diagram.java(上記で使用したサンプルコードを利用します)
ファイル名:Rectangle.java(上記で使用したサンプルコードを利用します)
ファイル名:Triangle.java
public class Triangle implements Diagram {
double width;
double height;
Triangle() {
this.width = 0;
this.height = 0;
}
public Triangle(double width, double height){
this.width = width;
this.height = height;
}
public double getArea() {
return (width * height / 2);
}
}
ファイル名:InterfaceTest?.java
public class InterfaceTest {
public static void main(String[] args) {
Diagram zukei1 = new Rectangle(10, 20);
Diagram zukei2 = new Triangle(10,20);
System.out.println("zukei1の面積=" + zukei1.getArea());
System.out.println("zukei2の面積=" + zukei2.getArea());
}
}
キャスト †
キャストとは指定した型として処理を行ってもらうことです。
クラスにおいてキャストが可能なのは、継承関係にあるクラスとの間でのみです。
継承関係のうちスーパークラスへのキャストは「アップキャスト」、サブクラスへのキャストは「ダウンキャスト」と呼ばれます。
- アップキャスト
サブクラスはスーパークラスに代入することができます
RectangleのサブクラスBoxは、Rectangleとして処理を行うことができます。
ファイル名:Rectangle.java(先ほど使用したサンプルコードをそのまま使用します)
ファイル名:Box.java
public class Box extends Rectangle {
double side;
public Box(){
this.width = 0;
this.height = 0;
this.side = 0;
}
public Box(double width, double height, double side){
this.width = width;
this.height = height;
this.side = side;
}
public double getVolume() {
return (this.width * this.height * this.side);
}
}
ファイル名:SuperAndSubTest?.java
public class SuperAndSubTest {
public static void main(String[] args) {
Rectangle rec = new Box(10.0, 12.0, 15.0);
System.out.println("recの面積=" + rec.getArea());
}
}
- ダウンキャスト
サブクラスの型へキャストするには明示的にクラス名を指定する必要があります。
代入先の変数 = (キャストしたい型) 元の変数;
以下の例ではRectangleクラス(スーパークラス)にBoxクラス(サブクラス)のインスタンスを代入して
再度Boxクラスの機能を使用する例です。
スーパークラスをサブクラスに代入するにはキャストする必要があります。
ただし、インスタンスが実際にBoxクラス(サブクラス)でなければプログラムは異常終了します。
ファイル名:CastTest1.java
public class CastTest1 {
public static void main(String[] args) {
Rectangle rec1 = new Box(5, 10, 20);
Box box1 = (Box)rec1;
System.out.println("box1の体積=" + box1.getVolume());
Rectangle rec2 = new Rectangle(8, 10);
Box box2 = (Box)rec2;
}
}
- instanceof
上記サンプルのような異常終了を避けるにはinstanceofという演算子を使用します。
instanceofは対象のインスタンスを特定することができます。
instanceofの使用方法です。結果はbooleanの値が返ってきます。
チェック対象となるインスタンス instanceof 特定したいクラス
instanceofを使用して、キャストを確実に行うことができます。
ファイル名:CastTest2.java
public class CastTest2 {
public static void main(String[] args) {
Rectangle rec = new Rectangle(5, 6);
System.out.println( "rec instanceof Box=" + (rec instanceof Box) );
if (rec instanceof Box) {
Box box = (Box)rec;
System.out.println("boxの体積=" + box.getVolume());
}
}
}
練習問題 †
- 人に関するクラスを作ってみましょう。
- インターフェース
- 抽象クラス
- NamePerson?
Personを実装する
フィールド - name
コンストラクタ - nameを設定する
抽象メソッド - showNameを実装しない
- クラス
- Men, Women
NamePerson?を継承する
showNameメソッドを実装する
- MainPerson?
mainメソッドを持つ実行するクラスとし、
MenとWomenを実装しshowNameメソッドを呼び出す
Java勉強会カリキュラムに戻る