初心者のJavaプログラミング

プログラミングガチ初心者がIT業界を目指して頑張ります。

【第24回】初心者のJavaプログラミング【パッケージ】

2連続投稿です。
今回はパッケージについてです。
package
import
等のキーワードが出てきます。
ターミナルやコマンドプロンプト上でのコンパイルと実行の仕方が通常と違うので、そこのあたりも説明していきます。
そんなに難しくないはずです。

パッケージとは

パッケージとは、辞書的な説明をすると、クラスやインターフェイスの集まりのこと、となっています。
意味を持たせた集まりというイメージでしょうか。
Javaのパッケージ = ディレクトリ(フォルダ)
だとイメージすれば良いのではないかと思います。

パッケージの割り当て方

1つのソースファイルに含まれるクラスとインターフェイスを特定のパッケージに割り当てる方法があります。
めちゃくちゃ簡単で、

package パッケージ名;

を、一番最初の行に書きます。

また、複数のパッケージを階層的にすることも出来ます。
この場合はピリオドで区切ります。


余談ですが、会社で使うときにはパッケージ名としてドメイン名を使用するのが一般的とのことです。
ドメインが、
matoowo.co.jp
の場合、パッケージ名は、
jp.co.matoowo.~
みたいに逆から書いていくそうです。
その後ろにアプリ名、機能名を書いていくみたいです。
jp.co.matoowo.aprication1.dao
って言う感じです。
働いたことがないので詳しいことは良く分かりませんw

機能名ですが、

  • dao(データベースアクセス用)
  • dto(画面表示用)
  • entity(データ)
  • logic(処理)
  • controller(仲介)
  • property(設定)

らへんが使われることが多いみたいです。

また、今まで上げたソースではパッケージの指定なんて1回もしたことはなかったと思います。
パッケージの指定をしなかった場合は、デフォルトパッケージ(名前無し、無名)のパッケージに割り当てられることになります。

やや脱線しましたが、パッケージの割り当て方としてはこんな感じですね。

具体的なやり方

例を見てもらった方が分かりやすいと思うので、まず例を。

package p;

class PackageSample {
	public static void main(String[] args) {
		A a = new A();
		B b = new B();
		C c = new C();

		a.a1();
		b.b1();
		c.c1();
	}
}
package p;

class A {
	void a1() {
		System.out.println("A");
	}
}
package p;

class B {
	void b1() {
		System.out.println("B");
	}
}
package p;

class C {
	void c1() {
		System.out.println("C");
	}
}

こんな感じで、4つのソースファイルを用意します。
こいつらを全部1つのパッケージに指定するので、pというパッケージに割り当てます。
それぞれのソースファイルの最初の行ですね。

ここまではいいと思うんですが、コレをコンパイルする方法が今までと違います。
私の場合は、
Documents/Java/p
の中にこれらのソースファイルを置きました。
そうしたらまずパッケージの親ディレクトリをカレントディレクトリにします。
私の場合だと、
Documents/Java
です。
移動したらコンパイルするために、ここで次のようなコマンドを打ちます。
javac p/*.java
windowsでは
/ ではなくて¥を打ちます。
このp/*.javaの意味ですが、
/はディレクトリを指定する意味ですよね。*は全部って言う意味があるらしいです。
なので「pのディレクトリの中にある、拡張子が.javaのファイル全部に対してコンパイルします」という命令です。

このコマンドを実行するといつも通り、.classファイルがpディレクトリの中に出来上がると思います。

次に実行の方法ですが、
java p.PackageSample
という風に打ちます。
JVMの引数として、クラス名を完全修飾クラス名で指定しなければなりません。
完全修飾クラス名とはパッケージ名とクラス名を合わせたものです。
ですので、
java PackageSample
ではなく、完全修飾クラス名で
java p.PackageSample
とうようにしてやる必要があります。

無事実行されるはずです。

import

別のパッケージ内のクラスやインターフェイスを使いたい場合に使用する方法です。
例えば、java.utilパッケージのクラスやインターフェイスを使いたい場合等に利用します。

import java.util.*;

というように書きます。
*なので、java.utilパッケージの中の全てのクラスやインターフェイスを指定していることになります。

Javaのリファレンスを見るとこのようなパッケージがうるとらたくさんあります。
車輪の再発明とならないように、調べていいのがあったら積極的に使っていくのがいいぜ!


パッケージはコレで終了です。
次回は例外処理です。

【第23回】初心者のJavaプログラミング【インターフェイスの継承•instanceof演算子】

こんばんは。
最近は基本情報の勉強に重きを置いているので、なかなか更新する機会が少なくなっています。
申し訳ないです。
試験日が10月19日なので、そろそろ過去問をがっつりやらなきゃだめだと思うので、日々過去問を解いています。

今日はインターフェイスの継承についてです。

インターフェイスの継承(書き方)

方法は通常のクラスの継承(拡張)と同じで、extendsキーワードを使用します。
前回も説明しましたが、Javaでは多重継承を許していません。ですがインターフェイスの場合は多重継承が出来ます。
その方法も前回書いたので省略します。

じゃあそもそも、なんでJavaでは多重継承を許してないのでしょうか。

Javaが多重継承を許していない訳

複数のスーパーインターフェイス内で同じ名前の変数やメソッドが宣言されていると、サブクラスからするとどっちを参照すればいいのか分からないですよね。
結果コンパイルエラーが発生します。
ここら辺がちょっとややこしいので多重継承は許していないみたいです。

instanceof演算子

オブジェクトのクラスやオブジェクトに実装されているインターフェイスを確認するための演算子です。

変数名 instanceof クラス名(またはインターフェイス名)

このように書きます。
そして変数がinstanceofの後に書いてあるクラス名であれば"true"が返されます。違っている場合は"false"が返されます。

インターフェイスはこのくらいです。
あまり真新しいことはないです。

次回はパッケージについてです。

【第22回】初心者のJavaプログラミング【インターフェイス】

こんばんは。
ここ2、3日寒いですね。朝方とか羽毛布団にくるまっていましたw

今日はインターフェイスです。

インターフェイスとは

インターフェイスとは、定数とメソッド宣言を1つにまとめたものです。
というように教科書に記載してありますが、よくわかりません。
クラスと何が違うのというところですが、まだ私自身違いが良く分かっていません。
抽象クラスをさらに押し進めたもの、っていうように考えてもらってかまわない、と先生はおっしゃっていたのできっとそうなんでしょうw そういうことにしましょう。

じゃあ抽象クラスと何が違うの?となる訳ですが、
大きな違いは、多重継承ができることだと思います。
どこかで書いたと思いますが、Javaは多重継承を許していません(C++は許しているみたいです)
ですが、インターフェイスの場合は、複数インターフェイスを1つのクラスに実装することが出来ます。

ここで注意点なのですが、宣言と実装は別ということです。
はじめに定数とメソッドの宣言をひとつにまとめたものと書きました。メソッドをまとめたものではないです。メソッドの宣言をまとめたものになります。

メソッドの宣言でメソッドの機能を書きます。メソッドの中身がない状態です。
メソッドの実装でメソッドの中身を書きます。どのような動作をするかということです。
例えばリモコンで言うと、
メソッドの宣言は、
「音量上げるボタンを押す」
「音量下げるボタンを押す」
といったものです。
それに対して、メソッドの実装は、宣言された「音量を上げるボタンを押す」「音量を下げるボタンを押す」メソッドの中身のことです。
音量を上げるボタンを1回押したら音量を1上げる。2回押したら2上げる。音量がMAXまでいったらそれ以上上がらないようにする。ある一定の音量まで上げると、聴力を失う危険性があります、等といった警告を出す。
というような実際の動きの部分を実装と言います。

Javaでのインターフェイス宣言の仕方

一般的には次のように書きます。

interface インターフェイス名 {
  // 定数
  定数1;
  定数2 = 2;
  
  // メソッドの宣言
  void upSounds(); //< 宣言だけ。実装しちゃだめ。
  void downSounds() {
    // こんな風に実装はしちゃだめ。できない。
  }
}

普通のクラスの宣言の仕方と同じ要領です。
ただ、メソッドの中身を書いちゃだめってとこだけが重要です。
インターフェイスは動作の中身ではなく、どんな機能を持っているかがユーザーや他のクラスが分かればいいのです。メソッドの中身をわざわざ他クラスに見せる必要はないということです。カプセル化の話にもつながってきますね(たぶん...)

宣言したので、実装もしなきゃですよね。そうでなければ意味がありません。
メソッドを宣言しときながら実装を書かないと、なんじゃこりゃーってことになるので(音量上げるボタン押しても何も起こらないze!)、宣言したメソッドの中身は必ず実装します。
次は実装の仕方です。

Javaでのインターフェイス実装の仕方

class クラス名 implements 実装するインターフェイス名 {
  public void upSounds() {
    // 中身を書いていく
  }
  public void downSounds() {
    // 中身を書いていく
  }
}

上記のようになります。
継承のextendsみたいな要領で書いていきます。

また、1つのクラスに複数インターフェイスを実装できるので、

class クラス名 implements インターフェイス1, インターフェイス2 {}

というようなことも出来ます。
この時ももちろん全てのメソッドの中身を書かなければなりません。

継承ではこんな風にはかけませんでしたよね。


インターフェイス自体も継承が出来ます。
そこらへんと、それ周りの説明は次回にします。

よだーん
インターフェイス = 取り扱い説明書みたいなイメージなのですが、合っているのでしょうかw
リモコンそのものがインターフェイスみたいなイメージです。
少し不安です。

【第21回】初心者のJavaプログラミング【継承と変数•オーバーライド•コンストラクタ】

継承において、スーパークラスの属性やメソッドはサブクラスが相続します。
つまり、サブクラスではスーパークラスの属性やメソッドが使えます。
前々回あたりにやりました。

継承と変数

スーパークラスと同じ名前の変数をサブクラスで作った場合はどうなるでしょうか。
この場合は、サブクラスで作った変数がスーパークラスの変数を隠してしまいます。
となると、スーパークラスの変数はサブクラスから参照することができない!
と思いきや、やっぱりちゃんとサブクラスから参照できる機能がJavaにはあるんですね。
superというキーワードを使うと出来ます。
super.変数名
というようにサブクラス内で使用すれば、スーパークラスの同じ名前の変数を参照することが出来ます。
注意点ですが、2つ上のスーパークラスの変数にはアクセスできません。
super.super.変数名
といった使い方は出来ないということです。

そんじゃいつもの通り例を。

class Goku {
	// 悟空の身長と体重
	double height = 180.;
	double weight = 70.;
}

class Gohan extends Goku{
	// ご飯の身長と体重
	double height = 170.;
	double weight = 60.;
	// 悟空の身長を参照
	double getGokuHeight() {
		return super.height;
	}
}

class GokuGohan {
	public static void main(String[] args) {
		Gohan gohan = new Gohan();
		
		System.out.println(gohan.height);
		// サブクラスの悟飯から悟空の身長を呼び出す。
		System.out.println(gohan.getGokuHeight());
	}
}

メソッドのオーバーライド

同じシグネチャを持つメソッドスーパークラスにもある場合、スーパークラスメソッドが実行されずに、サブクラスのメソッドが実行されます。
シグネチャとは前もやりましたが、
メソッド名、引数の数、引数の型の組み合わせのことです。注意点ですが、戻り値の型はシグネチャに含まれません!
このことを知らなくて、なんかの問題ができませんでしたw

これは具体的な例を見た方が分かりやすいので、例を出します。

class Goku {
	void kamehameha() {
		System.out.println("おら悟空。カメハメ波!!");
	}
}

class Gohan extends Goku{
	void kamehameha() {
		System.out.println("ひゃっほーおら悟飯。カメハメ波!!");
	}
}

class GokuGohan {
	public static void main(String[] args) {
		Goku goku = new Goku();
		goku.kamehameha();

		Gohan gohan = new Gohan();
		gohan.kamehameha(); //< オーバーライド

		// 要注意!!
		Goku test = new Gohan();
		test.kamehameha(); //< オーバーライド
	}
}

mainメソッド内の、
Gohan gohan = new Gohan();
というところがオーバーライドです。
スーパークラスのkamehameha()メソッド
サブクラスのkamehameha()メソッド
シグネチャが同じですよね。
なので、スーパークラスのkamehameha()ではなく、
サブクラスのkamehameha()が呼ばれます。

問題は一番したのやつです。
Goku test = new Gohan();
です。
変数の型はスーパークラスであるGokuですね。
ですがオブジェクトそのものの型はGohanですよね。
どのkamehameha()メソッドを実行するのかを決定するのは、
変数の型ではなく、オブジェクトそのものの型です。
なのでこの場合はGokuではなく、Gohanのkamehameha()が呼ばれることになります。

new コンストラクタ()でオブジェクトの参照が渡されることを思い出せば普通に理解できますが、
勘違いしやすいところです。
気をつけましょう!!

ちなみに、メソッドも変数と同じく、
super.メソッド名();
というかたちで、スーパークラスメソッドを使用できます。

継承とコンストラクタ

クラスの属性とメソッドはそのクラスだけではなく、スーパークラスにも定義されています。
なので、そのクラスだけコンストラクタを実行して初期化するだけだと、適切な初期化が出来ません。
また、スーパークラスで定義された属性とメソッドはサブクラスのコンストラクタを実行する前に、適切に初期化されてなければなりません。
つまり、スーパークラスコンストラクタがサブクラスのコンストラクタより先に実行されることになります。

ここは、そうなんだーと思って検証してみるくらいでいいのかなって思います。


以上でクラス関係の所は終了です。
あとは、クラスの修飾子(publicとかprivateとか)は時間があるときに確認する感じでいいと思います。
余裕があれば書いていきますが、最近余裕がなくなってきたので厳しいかもですw


次からはインターフェイスに入ります。

【第20回】初心者のJavaプログラミング【特化としての継承】

こんばんは。今回は前回の続きです。
前回は汎化の継承というものをやりました。
物事の抽象的な部分に注目し、概念の階層を構築していくのが汎化という作業です。
例えばですと、消しゴム、ボールペン、鉛筆に共通の文房具という抽象的な概念を切り出して、それを基底クラスにします。

今回は特化の継承というものをやります。
考え方は同じです。

「汎化としての継承」と「特化としての継承」

汎化としての継承は、前回説明したとおりで、基底クラスを探し出して作ることです。
それに対して、特化としての継承はその名の通りですが、派生クラスを作りだすことです。
文房具クラスから鉛筆クラス、消しゴムクラス、ボールペンクラスを作りだすのが特化です。
元のクラスがどちらかということが違うだけです。やっていることは2つとも変わりません。
ですが、どっちかというと汎化のほうが難しいなと感じます。
やっぱり文房具と鉛筆を比べると、どっちが具体的かというと、鉛筆のほうが遥かに具体的だと思います。なので、文房具クラスを基底クラスにするという風に考えることの方が難しい気がします。

Javaにおける継承

ここからは書き方の説明です。
スーパークラスとサブクラスの関係について書きます。

スーパークラスはそのクラスのオブジェクト、またはサブクラスのオブジェクトを参照できます。
よーするに、intとdoubleみたいな関係じゃないすかね?(多分違うかもw)
スーパークラスの方が大きいのでサブクラスの参照を代入してもおっけーみたいな。
これ結構重要な機能らしいです。

以下例です。

// 文房具クラス(スーパークラス)
class Bunbobu {}
// 文房具のサブクラス
class Pencil extends Bunbobu{}
class Eraser extends Bunbobu{}
class BallPointPen extends Bunbobu{}

class InheritanceSample {
	public static void main(String[] args) {
		// 文房具クラスの変数を準備する。
		Bunbobu item;

		// サブクラスのオブジェクトの参照を入れる
		item = new Pencil();
		System.out.println("Pencilオブジェクトの参照");

		item = new Eraser();
		System.out.println("Eraserオブジェクトの参照");

		item = new BallPointPen();
		System.out.println("BallPointPenオブジェクトの参照");

		// 試しにサブクラスの変数にスーパークラスの参照を入れてみるが、
		// コンパイルエラーが出ます
		// サブクラスからは親のオブジェクトを参照できないということになります。
		Eraser items = new Bunbobu();
	}
}

親は子のアドレスを持つことができるということですね。


今日はこのくらいで。
次回は継承と変数の関係、メソッドのオーバーライド、継承におけるコンストラクタあたりを書いていこうと思います。

ではでは。

【第19回】初心者のJavaプログラミング【継承】

こんばんは。
かなり時間が空いてしまいました。
なかなか書く時間がなかったです、すみません。

今回はクラスの継承についてです。
継承とはなんぞやからやって行きます。

継承

オブジェクト指向を勉強していると継承という概念が出てくると思います。
今まで継承の使い方(コードの書き方)は知っていたんですが、そんなに便利なもんなの?
と思っていました。
最近その辺が分かってきたというか、あーこれがオブジェクト指向か〜と思うようになってきたので、書き方というよりは、
継承そのものについて書いていく予定です。

いきなり例をだします。今学校に通っているので、学校の例を。
学校でテストってありますよね。その管理をするシステムを考えます。
システムを作るにあたって、考えられるクラスは「生徒クラス」、「先生クラス」が考えられます。

じゃあまず生徒クラスの属性、機能を考えていきたいところですが、
今回は簡単に属性だけを考えていくことにします。

考えられる属性としては、

  • 生年月日
  • 名前
  • 出身
  • 所属組

でしょうか。ここらへんは適当ですw

次に、先生クラスを考えていきます。

  • 生年月日
  • 名前
  • 出身
  • 担当科目

でしょうか。ここも適当ですw

類似点から抽象的なものを探す

気付いた方も多いと思いますが、この2つのクラスの属性って、ほぼおなじですよねw
生年月日、名前、出身が共通の属性になります。
すぐに、「これをひとまとめにすればいいんだ!」
という風に考えるのは、やや危険な気がします。
こういうときは、なぜ共通の属性がでてくるんだろう?
と考えます。
なぜなぜ作戦ですね。
すぐ解決方法を考えるのは良くないと思います。
ん〜なんで共通の属性がでてくるんだろう。これは難しく考えすぎるとドツボにはまります。
簡単に考えます。生徒、先生はともに人です。
ばかばかしいかもしれませんが、この考え方が大事です。この場合人または人物がクラスになります。
複数のクラスから類似点を探し出します。このとき探し出したものは抽象的なものになることが多いです。
だから結構探し出すのは難しいです。
犬、猫、ゴリラ。
共通点はほ乳類とかになりますね。
人物もほ乳類もあまり具体的にイメージすることができないですよね。

で、抽象的な人物という共通項が見つかりましたね。
これをどうするかというと、独立したクラスとして扱います。
このような仕組みを継承(汎化としての継承)といいます。

あるクラスが、別のクラスの性質をそのまま引き継ぎます。
この例だと、
生徒クラスが人物クラスの性質を引き継いでいる。
先生クラスが人物クラスの性質を引き継いでいる。
この関係が継承です。

こんなイメージです。
f:id:fightingneetkun:20140821234635p:plain
人物クラスの性質を引き継ぐので、生徒、先生クラスには書かれていませんが、
実際には生年月日、名前、出身の属性を持ってます。
この時の人物クラスをスーパークラス、生徒、先生クラスをサブクラスと言います。
これは相対的なものです。
また、複数スーパークラスを継承すること(多重継承)はJavaは許してません。
C++は許しているみたいです。

最後にこの例をJavaで書くとこのようになります。

class 人物 {
  生年月日;
  名前;
  出身;
}

class 生徒 extends 人物 {
  所属組;
}

class 先生 extends 人物 {
  担当科目;
}

多分考え方が分かっていれば、extendsが継承を表すものなんだなーと分かると思います。

ちょっと眠くなってきてしまったので、続きは次回ですw