2009年8月8日土曜日

【JT】4 クラスとオブジェクト (その3)


** クラス詳説
*** メソッドから値を返す
- 呼び出し元に制御を返す場合分け
- メソッド内にて実行する文が無くなった。
- return文の実行として。
- メソッド内で例外がスローされた。
- 呼び出し元に値を返す。
- 呼び出し元に返す値の型は、メソッド宣言にて指
定する。
- 呼び出し元への値の返却は、return文で実施する。
- return文に付与する式や値の型と、戻り値型は一
致しなければならない。
- ただし、戻り型がクラスの場合、returnするものの
型はそのサブクラスでもよい。これはメソッドの値
返却の話題ではなく、クラスシステムの話題じゃな
いかなぁ。
- この技法を共変戻り型(covariant return typeと
いう。
- また、戻り型がvoidのときは、return文を省略して
もよい。return文を入れるときは、式を記述しない
return;とする。
*** キーワードthisを使う
- キーワード this はカレントオブジェクトを表す。
- 使用例:シャドウイングの回避

public class Point {
public int x = 0;
public int y = 0;

public Point(int x, int y) {
this.x = x;
this.y = y;
}
}

- おもしろい。thisは現在の文脈におけるグローバル
環境を指す、みたいなもんだな。
- 使用例:同一クラス内の別コンストラクタを指す

public class Rectangle {
private int x, y;
private int width, height;

public Rectangle() {
this(0,0,0,0);
}

public Rectangle(int width, int height) {
this(0,0,width,height);
}

public Rectangle(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
*** クラスのメンバーへのアクセスを制御する
- この本、用語の運用がいまいちなところがある。{修
飾子,アクセス修飾子}について、その関係をちゃんと
説明せずに、同じキーワードについて入り乱れて使っ
ている。
- アクセス制御:アクセス修飾子などを用いてアクセ
スを制御する機構をアクセス制御と呼ぶ。
- アクセス制御による制御は、対象を2階層に分類して
いる。
- トップレベル :クラス等
- メンバーレベル:クラスのメンバー等
- トップレベルにおけるアクセスレベル

| アクセス修飾子 | パッケージ | 全世界 |
|----------------+------------+--------|
| public | Y | Y |
| 修飾子なし | Y | N |


- メンバーレベルにおけるアクセスレベル

| アクセス修飾子 | クラス | パッケージ | サブクラス | 全世界 |
|----------------+--------+------------+------------+--------|
| public | Y | Y | Y | Y |
| protected | Y | Y | Y | N |
| 修飾子なし | Y | Y | N | N |
| private | Y | N | N | N |

- クラスは、そのメンバーが属するクラス。
- パッケージは、そのメンバーが属するクラスが属
するパッケージ。
- サブクラスは、そのメンバーが属するクラスのサ
ブクラス。
- このアクセス制御というのはどういう風に位置付け
たらいいか。
- まず、Javaでは、Common Lispと異なり、名前空間
はクラス毎である。(Common Lispはパッケージ毎)
- そこで名前の可視性の定義はクラス毎(及びそれ以
上)となる。
- そのような違いがあるだけで、アクセス制御が名
前の可視性の指定であるという点は、Javaと
Common Lispに違いはない。
*** インスタンスメンバーとクラスメンバー
- キーワード static を紹介する。
- クラス変数
- フィールドの宣言にあたり、修飾子 static をつ
けるとクラス変数になる。(つけなければインスタ
ンス変数)
- クラス変数を宣言するとメモリが確保される。その
メモリが、クラス変数の名前が指す場所であり、値
が格納されている。その固定的な束縛は、そのクラ
スの任意のインスタンスに含まれている。
- クラス変数はインスタンスがひとつも存在しなく
ても利用可能。
- 例

public class Bicycle {
private int cadence;
private int gear;
private int speed;
private int id;
private static int numberOfBicycles = 0;

public Bicycle(int startCadence,
int startSpeed,
int startGear) {
gear = startGear;
cadence = startCadence;
speed = startSpeed;
id = ++ numberOfBicycles;
}
public int getID() {
return id;
}
}

- クラス変数に、当該クラス外からアクセスすると
きなどは、

クラス名.単純名

という構文が使える。インスタンスがあるときは、
インスタンスの参照経由でもアクセスできる。
- クラスメソッド
- メソッドの宣言において、修飾子staticをつける
とクラスメソッドになる。
- クラスメソッドは、そのクラスのインスタンスが
一つも存在しなくとも利用できる。
- 変数とメソッドの参照ルール
- IM : インスタンスメソッド
- IV : インスタンス変数
- CM : クラスメソッド
- CV : クラス変数
- 縦軸は文脈。(参照する側)
- 横軸は参照されるもの。

| | IM | IV | CM | CV |
|----+----------------------+----------------------+--------+--------|
| IM | 単純名 | 単純名 | 単純名 | 単純名 |
| CM | オブジェクト参照経由 | オブジェクト参照経由 | 単純名 | 単純名 |

- 本では文章で書いてあるから複雑かな、と思って
しまうが、表にすると至ってシンプル。
- 定数
- 修飾子 static と修飾子 final を両方同時に宣言
することによって、定数を表現することがある。
- 修飾子 final はその変数が変更不可能であること
を指示し、変更処理の対象になっていると、コン
パイラがエラーとなる。
*** フィールドを初期化する
- この項、次のものがでてくる。
- static初期化ブロック
- 初期化ブロック
- finalメソッド
- 正直、ここの説明で理解することは難しそうなので割
愛。
*** クラスとオブジェクトのまとめ
*** 設問と演習:クラス
**** 設問
- 1.
- a. x
- b. y
- c.
a.y = 5
b.y = 6
a.x = 2
b.x = 2
**** 演習
- 1. こんな感じ?

Card.java
---
public class Card {
private int rank; // [1,13]
private String suit; // "Diamond", "Spade", "Heart", "Club"

Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
Card() {
this(1,"Diamond");
}

public int getRank() {
return rank;
}
public String getSuit() {
return suit;
}
}
---

Deck.java
---
public class Deck {
private Card[] cards = new Card[52];
Deck() {
String[] suits = {"Diamond", "Spade", "Heart", "Club"};

for(int i=0;i<4;i++) { // index of suits
for(int j=0;j<13;j++){ // index of rank
cards[j + i * 13] = new Card(j + 1, suits[i]);
}
}
}

public void showCards() {
for(Card card : cards) {
System.out.println("suit:" + card.getSuit() + ", " +
"rank:" + card.getRank());
}
}
}
---

PlayingCardsDemo.java
---
class PlayingCardsDemo {
public static void main(String[] args) {
Deck myDeck = new Deck();
myDeck.showCards();
}
}
---

*** 設問と演習:オブジェクト
**** 設問
- 1. Rectangleオブジェクトを生成していない。
- 2. Pointオブジェクト : 1, Rectangleオブジェクト : 1
- 3. 参照を0にする。
**** 演習
- 1. こんな感じ?
public class SomethingIsWrong {
public static void main(String[] args) {
Rectangle myRect = new Rectangle();
myRect.width = 40;
myRect.height = 50;
System.out.println("myRect's area is " + myRect.area());
}

}
- 2. こんな感じ?
public class NumberHolderDemo {
public static void main(String[] args) {
NumberHolder myNum = new NumberHolder();
myNum.anInt = 10;
myNum.aFloat = 1.03F;
System.out.println("#<Class myNum: anInt=" + myNum.anInt +
", aFloat=" + myNum.aFloat + ">");
}
}


この章、長い!
こつこつ。

0 件のコメント: