** 入れ子のクラス
- 入れ子クラス:Javaでは、クラスの中で別のクラスを
定義できる。これはCLOSではできないような。
- 入れ子クラスは二種類ある。
- static
- 非static (内部クラスとも呼ばれる)
*** なぜ入れ子のクラスを使うのか
- 入れ子クラスを使う3つの理由
- クラスのグループ化
- あるクラスが、別のあるクラスにとってのみ意
味をもつときにグループ化として使える。
- カプセル化
- まあ、そうなんですが。。。
- メンテナンスの容易性
- クラス定義とその利用箇所が近くなるので。
- うーん。いまいち、入れ子クラスの有用性がわから
ない。。。
*** staticな入れ子のクラス
- 特になし。
*** 内部クラス
- 特になし。
*** 内部クラスの例
- お、例を書いてみると有用性が見えてきた。自分な
りのまとめを。
- まず、クラスが概念的に大きなものであるとき、
メソッドをフラットに並べるのではなく、分類し
たいという内部概念が発生することがあるのだろ
う。そのときそれを入れ子クラスで表現する。
- 付随的な効果として、名前空間の整理があるだろう。
前項のような概念構造とのときにクラス内フラット
に、もしくはトップレベルにその名前が存在する
のはよろしくない。
- また、同じことの違う側面だが、Javaではデータ構
造をクラスで表現するので、ある処理の内部で、そ
して内部のみで必要なようなデータ構造がでてくる
こともある。するとクラスをニーズがあるまさに
その局所で定義できた方がよい。
- 内部クラスには、他のメンバと同じように修飾子を
つけることができ、意味も同じ。
- ローカル内部クラスと匿名内部クラス
- ローカル内部クラス
- メソッドの中でクラスを定義。
- 匿名内部クラス
- ローカル内部クラスで名前が無いもの。
*** 入れ子クラスのまとめ
- スコープという言葉がでてくるが、ここでいうスコー
プがなんなのかの定義がないので正直理解できない。
- チュートリアルとしては、入れ子クラスは簡単な紹
介のみというスタンスのようなので、先に進む。
*** 設問と演習:入れ子のクラス
**** 設問
- 1.
- 学習素材がWebに置かれることもあるんだな。
- http://java.sun.com/docs/books/tutorial/java/javaOO/QandE/Problem.java
- あ、そうか。この本もともとオンライン版がある
んだ。
- さて、答は、staticな入れ子クラスからインスタ
ンス変数を参照するにはオブジェクト参照を介さ
ねばいけない。
- 2.
- a.
Box.Filter
- b.
Box.AccessibleBox
- c.
java.awt.Container.AccessibleAWTContainer
- d.
Box.Filter
- e.
new javax.swing.Box.Filter(min,pref,max);
// min pref max はDimensionクラスのインスタンス。
**** 演習
- こうなった。
InnerClass2 $ java Class1
InnerClass1: getString invoked.
InnerClass1: getAnotherString invoked.
InnerClass2 $
- う、何を言いたいのが掴めない。
** 列挙型
- 列挙型(enum type)は型である。
- 列挙型は定数を複数含んでいる。定数の集合のよう
なもの。
- 定義の例は次のとおり。
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
- 列挙型は自動的にクラスでもある。(暗黙のうちに
java.lang.Enumを継承している。)よって、public な
上記Dayは、Day.javaにて定義しなければいけない。
- 列挙はこのままで配列なわけではない。staticメソッ
ドvaluesによってそれが得られる。
- うぉ。こういう風にデータ記述とfinalとコンストラ
クが連携するのか。。。
public enum Planet {
MERCURY (3.303e+21, 2.4397e6),
VENUS (4.869e+24, 6.0518e6),
EARTH (5.976e+24, 6.37814e6),
MARS (6.421e+23, 3.3972e6);
private final double mass;
private final double radius;
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
...
}
- listとsymbolがあればいいじゃん、とも思ってしま
う。
*** 設問と演習:列挙型
**** 演習
- 1. こんな感じ?
Rank.java
---
public enum Rank {
ACE (1),
TWO (2),
THREE (3),
FOUR (4),
FIVE (5),
SIX (6),
SEVEN (7),
EIGHT (8),
NINE (9),
TEN (10),
JACK (11),
QUEEN (12),
KING (13);
private final int number;
Rank(int number) {
this.number = number;
}
public int getNumber() {
return number;
}
}
---
Suit.java
---
public enum Suit {
DIAMOND, SPADE, HEART, CLUB
}
---
Card.java
---
public class Card {
private Rank rank;
private Suit suit;
Card(Rank rank, Suit suit) {
this.rank = rank;
this.suit = suit;
}
Card() {
this(Rank.ACE, Suit.DIAMOND);
}
public Rank getRank() {
return rank;
}
public Suit getSuit() {
return suit;
}
}
---
- 2. こんな感じ?
Deck.java
---
public class Deck {
private Card[] cards = new Card[52];
Deck() {
int i = 0; // index of cards
for (Suit s : Suit.values()) { // iterate for suits
for(Rank r : Rank.values()){ // iterate for ranks
cards[i] = new Card(r, s);
i++;
}
}
}
public void showCards() {
for(Card card : cards) {
System.out.println("suit:" + card.getSuit() + ", " +
"rank:" + card.getRank() + ", " +
"rank in number:" + card.getRank().getNumber());
}
}
}
---
PlayingCardsDemo.java // これは無変更
---
class PlayingCardsDemo {
public static void main(String[] args) {
Deck myDeck = new Deck();
myDeck.showCards();
}
}
---
** 注釈
- 注釈(annotation)はプログラムのメタデータである。
- コードの動作に直接は影響を及ぼさない。
- 注釈を利用するもの
- コンパイラ
エラー検出、警告抑止。
- 配備ツール
配備時のコード生成
- 実行時のインタラクション
注釈は実行時にも参照可能。
- 注釈は、各種宣言に付与できる。
- 例をいくつか。
@Author(
name = "Hoge Piyo",
date = "2009/8/9"
)
class MyClass() {}
@SuppressWarnings(value = "unchecked")
void myMethod() {}
*** ドキュメンテーション
- 注釈は型を持つ。
- 注釈の型は、Javaであらかじめ定義されているもの
と、ユーザが定義するものがある。
- ここでは、ユーザ定義の方法を示す。
- 例えばクラスのドキュメンテーションを注釈で実施
する。
- クラス前文型を定義する
@interface ClassPreamble {
String author();
String date();
int currentRevision() default 1;
}
- 使う。
@ClassPreamble {
author = "Hoge Piyo",
date = "2009/8/9",
currentRevision = 3
}
public class Puyo {
// Class codes
}
- Javadocで生成されたドキュメントにこの情報を入れ
るには、@ClassPreambleの定義を次のようにする。
import java.lang.annotation.*;
@Documented
@interface ClassPreamble {
String author();
String date();
int currentRevision() default 1;
}
- うーん。Javaってこういう風にどんどん構文や意味
が増えていくのかなぁ。。。
*** コンパイラが使用する注釈
- 言語仕様にて定義済みの注釈型。いずれもコンパイ
ラが使う。
- @Deprecated
これがついているものを使うとコンパイル時に警
告がでる。
- @Override
スーパークラスのメソッドをオーバーライドする
ことを明示する。これがなくてもオーバーライド
するが、オーバーライドする対象がスーパークラ
スに無いとコンパイルエラーになるので、エラー
の予防にはなる。
- @SuppressWarnings
警告表示を抑制する。警告には、"deprecated"と
"unchecked"の2つのカテゴリがあり、これを指定
できる。
- 例
@SuppressWarnings("deprecation")
@SuppressWarnings({"deprecation",
"unchecked"})
*** 注釈の処理
- 注釈プロセッサは、注釈に基づくアクションを実行す
る。位置的には、Cのマクロプロセッサみたいなもん
かなぁ。
- JDK6.0では、注釈プロセッサ(名前はapt)がJavaコン
パイラに組み込まれている。
- 注釈情報を実行時に利用するためには注釈型の定義
時に指定が必要。
- 例
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@interface SomeAnnotationForRuntime {
// ...
}
*** 設問と演習:注釈
**** 設問
- 1. うーん。わからない。javadocを書いていないこ
と?
- 2. コンパイルしたけど、何もおこらない。
AnnotationProblems $ javac Closable.java
AnnotationProblems $
- 3. なるほど。これを抑制するには、インターフェイ
スの@Deprecatedを外すしかない。
@SuppressWarningsはメソッドの定義時に対しては効
かないようだ。
この程度ちょこっと進むのにも、4時間くらいかかる。。。
なんとかならんかなぁ。
こつこつ。