※当サイトの記事には、広告・プロモーションが含まれます。

Java言語セミナーを受講して 6章

今回もJava言語セミナーを受講しての続きになるのですが、その前にORACLEによる発表でJava脆弱性について言っていて、「『6u113』『7u97』『8u73』より前のバージョンのJava SEをダウンロードしたユーザーはこれらを破棄して、代わりに6u113、7u97、8u73以降のバージョンをインストールすべきだ」とORACLE社は警告してるようです。

  詳しくは下記サイトへ

オラクル、「Java」脆弱性のパッチを公開--Windowsが「完全に乗っ取られる」恐れも - ZDNet Japan

オブジェクトにすることのメリット

前回、クラスを元にオブジェクトを作っていく話だったのですが、ORACLEの説明(What Is an Object?)によると、

Bundling code into individual software objects provides a number of benefits, including:

  1. Modularity: The source code for an object can be written and maintained independently of the source code for other objects. Once created, an object can be easily passed around inside the system.
  2. Information-hiding: By interacting only with an object's methods, the details of its internal implementation remain hidden from the outside world.
  3. Code re-use: If an object already exists (perhaps written by another software developer), you can use that object in your program. This allows specialists to implement/test/debug complex, task-specific objects, which you can then trust to run in your own code.
  4. Pluggability and debugging ease: If a particular object turns out to be problematic, you can simply remove it from your application and plug in a different object as its replacement. This is analogous to fixing mechanical problems in the real world. If a bolt breaks, you replace it, not the entire machine.

直訳すると、

『オブジェクトごとにコードをまとめることは、下記のような利益をもたらします。

  1. モジュール性:オブジェクトごとにソースコードが独立してるので、あるオブジェクトのソースコードの変更が他のオブジェクトのソースコードに影響を与えない。他に影響を与えないので、一度オブジェクトが作られれば、システムに簡単に組み込めます。
  2. データの隠蔽:オブジェクトのメソッドでのみプロパティに干渉できるので、オブジェクト内の実行結果に対して外部からの影響を与えないようにできる。
  3. コードの再利用:他の開発ソフトで記述されたオブジェクトでも、使うことができます。これは、専門家に、インプリメント/テスト/デバッグの複合したもの、特定のタスクのオブジェクトを許可するので、他で開発されたオブジェクトをあなた自身のコードの中で安心して使うことができます。
  4. 機能追加とデバッグのしやすさ:もし、特定のオブジェクトに問題があると判明した場合、そのオブジェクトを簡単にあなたのアプリケーションから取り除くことができ、そのオブジェクトの代わりに別のオブジェクトを代替として組み込めます。これは、現実の世界でいうところの、機械の故障を修理することに似ています。もし、ボルトが破損したら、そのボルトを取り換えますが、機械全体を代えることはありません。』 

といったようなことを言っているようです。

ということで、クラスについての続きをメモしていきたいと思います。

クラスの継承(Inheritance)

前回、Bicycleクラスでクラスについて記述していたので、今回もBicycleクラスをベースに考えていきたいと思います。

クラスの継承について、ORACLEの説明(What Is Inheritance?)では、

What Is Inheritance?

Different kinds of objects often have a certain amount in common with each other. Mountain bikes, road bikes, and tandem bikes, for example, all share the characteristics of bicycles (current speed, current pedal cadence, current gear). Yet each also defines additional features that make them different: tandem bicycles have two seats and two sets of handlebars; road bikes have drop handlebars; some mountain bikes have an additional chain ring, giving them a lower gear ratio.

Object-oriented programming allows classes to inherit commonly used state and behavior from other classes. In this example, Bicycle now becomes the superclass of MountainBike, RoadBike, and TandemBike. In the Java programming language, each class is allowed to have one direct superclass, and each superclass has the potential for an unlimited number of subclasses: 

直訳すると、

『いろんな種類のオブジェクトがあるけど、しばしばお互いに全く同じと思える共通した部分があると感じます。MountainBicycle、RoadBike、TandemBikeなどを例にとると、全てBicyclesの特性(スピード、ペダルの回転数、ギア)を共有してます。また、それぞれを異なるものとしている特徴が既に定義されていて:TandemBikeだと2つのシートと2つのハンドル、RoadBikeはハンドルを下げられ、MountainBikeではギアの比率をより低くするチェーンを持ってます。オブジェクト指向プログラミングでは、あるクラスが他のクラスから共通したstate(プロパティ)やbehavor(メソッド)を継承することができます。例として、Bicycleが、MountainBicycleRoadBikeTandemBikeのsuperclass(スーパークラス)になったとします。Java言語では、それぞれのクラスはsuperclass(スーパークラス)を1つだけ持つことができ、subclass(サブクラス)に関しては個数に制限はありません。』 

となっています。

ちなみに、下図はORACLEの継承のイメージ図です。

f:id:ts0818:20160210153426g:plain

 

共通してる部分をsuperclassとして、他の特徴的な部分をsubclassに任せようということらしいです。

継承の記述の仕方は、

class サブクラス extends スーパークラス{
  サブクラス独自のプロパティやメソッドを記述してもOK
}

となり、実際にBicycleクラスをスーパークラスとし、MountainBikeクラスをサブクラスとした例を取り上げます。

Bicycleクラスを用意

class Bicycle {

    int cadence = 0;
    int speed = 0;
    int gear = 1;

    void changeCadence(int newValue) {
         cadence = newValue;
    }

    void changeGear(int newValue) {
         gear = newValue;
    }

    void speedUp(int increment) {
         speed = speed + increment;   
    }

    void applyBrakes(int decrement) {
         speed = speed - decrement;
    }

    void printStates() {
         System.out.println("cadence:" +
             cadence + " speed:" + 
             speed + " gear:" + gear);
    }
}

 

MountainBikeクラスを用意

class MountainBike extends Bicycle {

    // new fields and methods defining 
    // a mountain bike would go here
    //サブクラス独自のプロパティとメソッド
    int energy = 10;
    void energyConsume(int time){
         energy = energy - time/60; 
    }
    void energyCharge(int supply){
         energy = energy + supply;  
    }
}

 

実行用のクラスを用意します。

class sample_test18{

  public static void main(String[] args){
  
// MountainBikeクラスのインスタンス(オブジェクト)を生成
    MountainBike bike3 = new MountainBike();
    bike3.changeCadence(8);   //スーパークラスのメソッド
    bike3.energyCharge(10);   //サブクラスのメソッド
    bike3.speedUp(10);        //スーパークラスのメソッド
// スーパークラスのプロパティcadenceを表示    
    System.out.println("cadence= " + bike3.cadence);
// サブクラスのプロパティenergyを表示    
    System.out.println("energy= " + bike3.energy);    
    
  }

}
    

実際にコマンドプロンプトで実行してみます。

windowsではjavacコマンドはソースSJISであると解釈して、コンパイルを行うようです。ファイルをUTF-8Nで保存していたので、今回はJavacコマンドのオプションで文字コードの問題を回避しました。(ファイルは全てC:¥sample¥java01に保存しています。

  詳しくは下記サイトへ

コマンドプロンプトでJAVAを動作させると日本語が文字化けする。 - ... - Yahoo!知恵袋

f:id:ts0818:20160210183933j:plain

継承関係を表した図のことを継承ツリーと呼ぶようで、下の図のようになります。

f:id:ts0818:20160210192624p:plain 

C++などでは「親クラス」を複数指定することが出来ますが、Javaでは「親クラス」は1つしか指定する事が出来ません(単一継承)。

  UMLについては下記サイトへ

UML入門 - IT専科

継承 - Java入門 - IT専科

JavaではじめるUML ( 第 2 回 ) | オブジェクトの広場

継承のルール

継承する際には他にもいろいろルールがあります。

  • 単一継承(親クラスは1つしか持てません)。
  • コンストラクターは継承されません。
  • 静的メンバ = staticメンバ(プロパティ・メソッド)は継承されません。
  • privateで修飾されたプロパティやメソッドは継承されません。
  • finalで修飾されたクラスは継承されません。

 

既存のクラスを元に新しいクラスを作成することは可能

f:id:ts0818:20160210204703p:plain

既存のクラスを元に新しいクラスを複数作成することは可能

f:id:ts0818:20160210204704p:plain

あるクラスを継承してるクラスを元にさらにサブクラスを作成することは可能

f:id:ts0818:20160210204705p:plain

複数クラスをもとに新しいクラスを作成することは不可

f:id:ts0818:20160210204706p:plain

 

変数のスコープ

変数には有効範囲があってそれぞれ使用できる範囲が異なります。

メンバ変数 ⇒ Fields(state) = プロパティ(クラスで定義した変数)のこと

ローカル変数 ⇒ if文やfor文、メソッドの中の変数のこと

変数にアクセスできる範囲のことを変数のスコープと呼ぶようです。

変数スコープのイメージ図

f:id:ts0818:20160210214532p:plain

 

コンストラク

クラスをインスタンス化した時に自動で呼び出されるものです。

  • 名前がクラス名と同じである
  • 戻り値を持たない

という特徴があります。 

  [修飾子] コンストラクタ名(引数){ }

実際にコンスタラクタを定義

class Bicycle01{

  int serialNumber;    // メンバ変数
// コンストラクタの定義
// thisは自分自身(自オブジェクト)を表すキーワードです。
// this.serialNumberでメンバ変数を参照
  Bicycle01(int serialNumber){
    this.serialNumber = serialNumber;
  }
// メンバ変数serialNumberを返すメソッド
  int getSerialNumber(){
    return serialNumber;
  }

}

実行クラスを定義します。 

class sample_test19{

  public static void main(String[] args){
// newキーワードでBicycleクラスをインスタンス化しオブジェクトを生成
// コンストラクタでメンバ変数serialNumberに100が代入される
    Bicycle01 bike01 = new Bicycle01(100);
// getSerialNumber()メソッドでメンバ変数serialNumberを取得し表示
    System.out.println("この自転車の製造番号は" + bike01.getSerialNumber() + "です。");
  }

}

実際にコマンドプロンプトで実行してみます。

f:id:ts0818:20160211015947j:plain

 

コンストラクタはクラスをnewキーワードでインスタンス化しオブジェクトを生成した時に自動で呼び出されます。

これまで、コンストラクタなんか定義してこなかったけど?と思った方、名探偵です。

Javaでは、コンストラクタを自分で定義しなかった場合、デフォルトで用意されてるコンストラクタが自動的に追加され実行されるようです。

これを、デフォルトコンストラクというようです。

デフォルトコンストラクタのイメージ図

f:id:ts0818:20160211110422p:plain

 

super( )でスーパークラスのコンストラクタを明示的に呼び出しています。

Bicycleは親クラスだから何も継承していないんじゃ?と思った方、名探偵です。

実は、Javaでは全てのクラスはjava.lang.Objectクラスを元にしているため、Javaにおけるクラスは全てObjectクラスのサブクラスと言えるようです。

いままで、newしてきたときにはデフォルトコンストラクタが実行されていたんですね。

デフォルトコンストラクタはクラスに1つもコンストラクタを定義しなかった場合のみコンパイルのタイミングで追加されるそうです。

オーバーロード

メソッドなどで定義側の引数のデータ型と呼び出し時の引数のデータ型は一致させなければなりません。 

実際に引数がint型のメソッドを持つクラスを定義します。

class Bicycle03{

// int型の引数のメソッド
  void jetInjection(int fuel){
    System.out.println(fuel + "万馬力");
  }
  
}

実行クラスを定義します。

class sample_test20{

  public static void main(String[] args){
    Bicycle bike03 = new Bicycle();
    bike03.jetInjection(100);       // OK
    bike03.jetInjection("suzuki");  // コンパイルエラー
  }
  
}

コマンドプロンプトで実行してみます。

引数の型が合っていませんと6行目でエラーが発生しました。 

f:id:ts0818:20160211021315j:plain

引数のデータ型によってメソッド名を変えるというのも良いのですが、Javaでは1つのクラスに同じ名前のメソッドやコンストラクタを複数定義できます。

これをオーバーロードと呼ぶそうです。 

オーバーロードは、引数の並びデータ型引数の数が異なっていること、が条件になります。

void jetInjection(){}
void jetInjection(int a){}
void jetInjection(int a, int b){}
void jetInjection(String s){}

Bicycle03.javaのBicycle03クラスをオーバーロードさせればエラーが無くなるということで、Bicycle03.javaを修正します。

class Bicycle03{

// int型の引数のメソッド
  void jetInjection(int fuel){
    System.out.println(fuel + "万馬力");
  }
// String型の引数のメソッド
  void jetInjection(String name){
    System.out.println(name + "ターボ");
  }
}

今度はエラーにならず実行されました。

f:id:ts0818:20160211025945j:plain

 

ここまでの内容も、下記の書籍を参考にさせていただいています。

ラクル認定資格教科書 Javaプログラマ Bronze SE 7/8 単行本(ソフトカバー) – 2015/10/10

f:id:ts0818:20160202070628j:plain

次回も、Java言語セミナーを受講してシリーズです。

是非、また読んでみてくださればと思います。 

今回はこのへんで。