1
プログラミング言語 3
第
05
回(2007
年10
月22
日)2/33
今日の配布物
片面の用紙
1
枚今日の課題が書かれています。
本日の出欠を兼ねています
3/33
今日やること
http://www.tnlab.ice.uec.ac.jp/~s-okubo/class/java06/
にアクセスすると、教材があります。
2007年10月22日分と書いてある部分が、本日の教材です。
本日の内容
クラスとインストラクタ(再復習)
前回の課題の解答
継承
サブクラスの書き方
オーバーライド
4/33
誤植:クラスの書き方
class Test {
}
class Test {
}
必要なら修飾子を書く(クラスの修飾子については次回以降)
class名を書く
int test01;
コンストラクタを書く。今日の話の後半 で説明。
public void push(int test03){
System.out.println(test01 + test03);
}
変数を宣言する
メソッドを書く。
classと書く
変数やメソッドを
クラスのメンバと言います 必要なら
staticと書く。
5/33
オブジェクト指向プログラミング
(再復習)
6/33
設計図の世界
概念とか設計図の世界
Test
int contents;• pushContents();
static int st_cont;
• static cont();
クラスは、設計図。
実物を作ったときに、どう いう仕様かを書いている。
設計図は、あくまでも設計図。
値を蓄えたり、メソッドを実行 したりはできない。
7/33
実物の世界も考えると...
概念とか設計図の世界 実物(オブジェクト)の世界
Test
int contents;• pushContents();
static int st_cont;
Test.st_cont=10;
• static cont();
• Test. cont(); クラス名.メンバ名でアクセスする。
今回は、Test.st_cont の様にする。
クラスでstaticが含まれている 変数とメソッドは、いきなり実 物が存在。
8/33
実物(オブジェクト)の生成
概念とか設計図の世界 実物(オブジェクト)の世界 contents = 10;
• pushContents();
Data1 Test
int contents;• pushContents();
static int st_cont; st_cont;
Test.st_cont=10;
• static cont();
• Test. cont();
• cont();
実物は、値を蓄えたり、
メソッドを実行したりできる。
9/33
実物(オブジェクト)の生成
概念とか設計図の世界 実物(オブジェクト)の世界 contents = 10;
• pushContents();
Data1 Test
int contents;• pushContents();
static int st_cont; st_cont;
Test.st_cont=10;
• static cont();
• Test. cont();
• cont();
設計図には、『contentsという整数を保 存する場所がある』と書いてあるので、
実物には、それがある。
10/33
実物(オブジェクト)の生成
概念とか設計図の世界 実物(オブジェクト)の世界 contents = 10;
• pushContents();
Data1 Test
int contents;• pushContents();
static int st_cont; st_cont;
Test.st_cont=10;
• static cont();
• Test. cont();
• cont();
設計図にstaticと書いてあるモノ に関しては、こちらを使用する。
11/33
実物(オブジェクト)の生成
概念とか設計図の世界 実物(オブジェクト)の世界 contents = 10;
• pushContents();
Data1 Test
int contents;• pushContents();
static int st_cont; st_cont;
Test.st_cont=10;
• static cont();
• Test. cont();
• cont();
contents = 20;
• pushContents();
Data2
st_cont;
• cont();
同じ設計図に基づいて、
2つめのオブジェクトを生成。
12/33
static で無い変数
概念とか設計図の世界 実物(オブジェクト)の世界 contents = 10;
• pushContents();
Data1 Test
int contents;• pushContents();
static int st_cont; st_cont;
Test.st_cont=10;
• static cont();
• Test. cont();
• cont();
contents = 20;
• pushContents();
Data2
st_cont;
• cont();
それぞれのオブジェクトが、値を保 存する場所を独自に持っている。
13/33
static な変数
概念とか設計図の世界 実物(オブジェクト)の世界
contents = 20;
• pushContents();
Data2
contents = 10;
• pushContents();
Data1 Test
int contents;• pushContents();
static int st_cont; st_cont;
st_cont;
Test.st_cont=10;
• static cont();
• Test.cont();
• cont();
• cont();
staticと書いてあるの で、同じものを利用。
それぞれのオブジェクトは、
独自に値を持たない!
14/33
static な変数に代入 その 1
概念とか設計図の世界 実物(オブジェクト)の世界
contents = 20;
• pushContents();
Data2
contents = 10;
• pushContents();
Data1 Test
int contents;• pushContents();
static int st_cont; st_cont;
st_cont;
Test.st_cont=15;
• static cont();
• Test.cont();
• cont();
• cont();
Test.st_cont=15とすれば、
Data1.st_cont も15に。
15/33
static な変数に代入 その 2
概念とか設計図の世界 実物(オブジェクト)の世界
contents = 20;
• pushContents();
Data2
contents = 10;
• pushContents();
Data1 Test
int contents;• pushContents();
static int st_cont; st_cont;
st_cont;
Test.st_cont=20;
• static cont();
• Test.cont();
• cont();
• cont();
ここに値を代入!
Data1.st_count=20
ここに代入と同じ結果に!
当然、 Data2.st_count も20になる!
16/33
前回の課題の解答
17/33
前回の課題
その1:
次のプログラムを実行しなさい。
レポートとして、
実行結果を報告しなさい。
static がついている変数に注目し、その
結果になった理由を説明しなさい。
class Test{
static int st_data;
int data;
public void test_func01(){
System.out.println(data);
}
public static void test_func02(){
System.out.println(st_data);
} }
class Test{
static int st_data;
int data;
public void test_func01(){
System.out.println(data);
}
public static void test_func02(){
System.out.println(st_data);
} }
サンプルプログラム内のクラス
data;
• test_func01();
設計図
st_data;
• test_func02();
public class Sample04a{
public static void main(String[] args){
Test dt01 = new Test();
Test dt02 = new Test();
public class Sample04a{
public static void main(String[] args){
Test dt01 = new Test();
Test dt02 = new Test();
サンプルプログラム main 内
data=0;
• test_func01();
dt01
st_data;
• test_func02();
data=0;
• test_func01();
dt02
st_data;
• test_func02();
Test st_data=0;
• test_func02();
[1/6]
dt01.data=100;
dt02.data=200;
System.out.println(dt01.data);
System.out.println(dt02.data);
dt01.data=100;
dt02.data=200;
System.out.println(dt01.data);
System.out.println(dt02.data);
サンプルプログラム main 内
data=100;
• test_func01();
dt01
st_data;
• test_func02();
data=200;
• test_func01();
dt02
st_data;
• test_func02();
Test st_data=0;
• test_func02();
それぞれのインスタン スメンバに代入。
コンソールに
と表示される。
100 200
[2/6]
System.out.println();
Test.st_data=300;
System.out.println(Test.st_data);
System.out.println(dt01.st_data);
System.out.println(dt02.st_data);
System.out.println();
Test.st_data=300;
System.out.println(Test.st_data);
System.out.println(dt01.st_data);
System.out.println(dt02.st_data);
サンプルプログラム main 内
data=100;
• test_func01();
dt01
st_data;
• test_func02();
data=200;
• test_func01();
dt02
st_data;
• test_func02();
Test
st_data=300;
• test_func02();
クラスメンバに300が 代入される。
コンソールに
と表示される。
300 300 300
[3/6]
System.out.println();
dt02.st_data=400;
System.out.println(Test.st_data);
System.out.println(dt01.st_data);
System.out.println(dt02.st_data);
System.out.println();
dt02.st_data=400;
System.out.println(Test.st_data);
System.out.println(dt01.st_data);
System.out.println(dt02.st_data);
サンプルプログラム main 内
data=100;
• test_func01();
dt01
st_data;
• test_func02();
data=200;
• test_func01();
dt02
st_data;
• test_func02();
Test
st_data=400;
• test_func02();
クラスメンバに400が 代入される。
コンソールに
と表示される。
400 400 400
[4/6]
ここに代入しよ うとすると...
実際には、
ここに代入!
System.out.println();
dt01.test_func01();
dt02.test_func01();
System.out.println();
dt01.test_func01();
dt02.test_func01();
サンプルプログラム main 内
data=100;
• test_func01();
dt01
st_data;
• test_func02();
data=200;
• test_func01();
dt02
st_data;
• test_func02();
Test
st_data=400;
• test_func02();
それぞれのインスタン スは、自分の持って いる値を出力。
コンソールに
と表示される。
100 200
[5/6]
dt01.test_func02();
dt02.test_func02();
Test.test_func02();
} }
dt01.test_func02();
dt02.test_func02();
Test.test_func02();
} }
サンプルプログラム main 内
data=100;
• test_func01();
dt01
st_data;
• test_func02();
data=200;
• test_func01();
dt02
st_data;
• test_func02();
Test
st_data=400;
• test_func02();
クラスオブジェクトが 実行される。
結局、みんな同じ事。
コンソールに
と表示される。
400 400 400
[6/6]
25/33
前回の課題
その2:
実行結果を報告しなさい。
それぞれのインスタンスが持つ変数
value 注目
し、その結果になった理由を説明しなさい。Sample04c.java をコンパイル、実行しなさい。
レポートとして、
26/33
回答
class Test{
int value;
Test(){
value=10;
}
Test(int value01){
value=value01*10;
} }
public class Sample04c{
public static void main(String[] args){
Test dt01 = new Test();
Test dt02 = new Test(100);
System.out.println(dt01.value);
System.out.println(dt02.value);
} }
2つ以上のコンストラクタが有る場合、
どちらが実行されるかは、引数で判断される。
引数が無いので、
こちらが実行される。
引数として 整数が一つ 渡されるので、
こちらが実行される。
コンソールに
と表示される。
10 1000
27/33
前回の課題
その3:
Sample04d.java に、『double型の引数と整数型
の引数を貰い、その除算の結果を出力するメソッドcalc』
を書き加えなさい。また、calc(10.5, 20.5)の次の行に
calc(10.5, 3) を加えて、実行しなさい。
28/33
もともとのプログラム:
public class Sample04d{
public static void main(String[] args){
calc(10,20);
calc(10.5,20.5);
}
public static void calc(int data01, int data02){
System.out.println(data01*data02);
}
public static void calc(double data01, double data02){
System.out.println(data01+data02);
} }
引数が(整数,整数)
なので、こちらが実行
引数が(double,double) なので、こちらが実行 同じクラスのメソッドは、
メソッド名だけで実行できます
29/33
解答例:
public class Sample04d{
public static void main(String[] args){
calc(10,20);
calc(10.5,20.5);
calc(10.5,3);
calc(10.5,3);
calc(10.5,3);
calc(10.5,3);
}
public static void calc(int data01, int data02){
System.out.println(data01*data02);
}
public static void calc(double data01, double data02){
System.out.println(data01+data02);
}
public static void calc(double data01, public static void calc(double data01, public static void calc(double data01,
public static void calc(double data01, int int int int data02){data02){data02){data02){
System.out.
System.out.
System.out.
System.out.printlnprintlnprintln(data01/data02);println(data01/data02);(data01/data02);(data01/data02);
} }}}}
コンソールに と表示される。
3.5
引数を double とintに
30/33
継承
31/33
継承とは
あるクラスが存在しているとき、それを流用して、違うク ラスを記述することができる!。
int data01;
• test_func01();
Test01 int data01;
• test_func01();
Test02
int data02;
もとのクラスをスーパークラス、新しくできたクラスをサ ブクラスと呼びます。
新しくできたサブクラスは、普通のクラスと同様の方法 でインスタンスを生成し、使えます。
32/33
サブクラスの書き方
Test02
int data02;
int data01;
• test_func01();
Test01
class サブクラス名 extends スーパークラス名 { 拡張したい内容を書く。
}
class サブクラス名 extends スーパークラス名 { 拡張したい内容を書く。
}
もとのクラスを拡張(
extends
)する形で書きます。直感的には、以下のような感じ。
拡張された 部分
スーパー クラス サブ
クラス
33/33
サブクラスの書き方例
Test02
int data02;
int data01;
• test_func01();
Test01
class Test01{
int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
class Test02 extends Test01{
class Test02 extends Test01{
class Test02 extends Test01{
int int int
int data02;data02;data02;data02;
}}}}
class Test01{
int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
class Test02 extends Test01{
class Test02 extends Test01{
class Test02 extends Test01{
int int int
int data02;data02;data02;data02;
}}}}
スーパークラス
拡張された内容
サブクラス
34/33
class Test01{
int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
int data02;
}
public class Sample04d{
public static void main(String[] args){
Test02 Test02Test02
Test02 dtdtdt02 = new Test02();dt02 = new Test02();02 = new Test02();02 = new Test02();
以下略 class Test01{
int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
int data02;
}
public class Sample04d{
public static void main(String[] args){
Test02 Test02 Test02
Test02 dtdtdtdt02 = new Test02();02 = new Test02();02 = new Test02();02 = new Test02();
以下略
生成されたインスタンス
dt02
data02;
data01;
• test_func01();
普通に生成
dt02.data01のように、
普通にアクセス
dt02.test_func01()のように、
普通にアクセス
35/33
復習:修飾子
class Test03{
private private private
private int data01;
public public public
public int data02;
func(){中略}
}
class Test03{
private private private
private int data01;
public public public
public int data02;
func(){中略}
}
data01;
dt01
data02;
Test03に基づいて 作られたオブジェクト
• func;
dt02 省略
• 省略
アクセス できない
アクセス できる data01にも
data02にも アクセスできる
その変数が、
どこからアクセスできるか、
範囲を指定
36/33
class Test01{
public public public
public int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
int data02;
void test_func02(){
data01=10;
} }
class Test01{
public publicpublic
public int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
int data02;
void test_func02(){
data01=10;
} }
スーパークラスの修飾子の影響 その 1 public 編
dt01(生成されたインスタンス)
data02;
data01;
• test_func01();
Test01
• test_func02();
dt01.test_func01は、
色々なところからアクセスできる dt02 省略
• 省略
37/33
class Test01{
private private private
private int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
int data02;
void test_func02(){
data01=10;
} }
class Test01{
private privateprivate
private int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
int data02;
void test_func02(){
data01=10;
} }
スーパークラスの修飾子の影響 その 2 private 編
dt01(生成されたインスタンス)
data02;
data01;
• test_func01();
Test01
• test_func02();
dt01.test_func02は、
data01にアクセスできないできないできないできない dt01.test_func01は、
data01に アクセスできる
dt02 省略
• 省略
38/33
修飾子 protected
サブクラスにはアクセスを許すが他のクラスにはアクセ スを許さないことを示すアクセス修飾子。
protected
がついたメンバは、サブクラス内からは
public
メンバのように別パッケージのクラスから見ると
private
メンバのよう にみることができる。
39/33
class Test01{
protected protected protected
protected int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
int data02;
void test_func02(){
data01=10;
} }
class Test01{
protected protectedprotected
protected int data01;
void test_func01(){中略}
}
class Test02 extends Test01{
int data02;
void test_func02(){
data01=10;
} }
修飾子 protected
dt01(生成されたインスタンス)
data02;
data01;
• test_func01();
Test01
• test_func02();
dt01.test_func02は、
data01にアクセスできるできるできるできる dt01.test_func01は、
data01に アクセスできる
dt02 省略
• 省略
40/33
class Test01{
int data01;
void void void
void test_functest_functest_functest_func01(){01(){01(){01(){中略中略中略中略}}}}
}
class Test02 extends Test01{
int data02;
void void void
void test_functest_functest_functest_func01(){01(){01(){01(){中略中略中略中略}}}}
}
class Test01{
int data01;
void void void
void test_functest_functest_func01(){test_func01(){01(){中略01(){中略中略}}}}中略 }
class Test02 extends Test01{
int data02;
void void void
void test_functest_functest_func01(){test_func01(){01(){中略01(){中略中略}}}}中略 }
メソッドのオーバーライド
dt01(生成されたインスタンス)
data02;
data01;
• test_func01();
Test01
• test_func01();
サブクラスの方で、
スーパークラスと同じ名前・引数の メソッドを定義した場合、
サブクラスで書いた方が有効に メソッドのオーバーライド
dt01.test_func01()として、
こちらが使われる。
こちらは使われない
41/33
class Test01{
int data01;
void void void
void test_functest_functest_functest_func01010101()()(){{{{中略() 中略中略中略}}}}
}
class Test02 extends Test01{
int data02;
void void void
void test_functest_functest_functest_func01010101((((intintintint j)j)j)j){{{{中略中略中略中略}}}}
}
class Test01{
int data01;
void void void
void test_functest_functest_func01test_func0101()01()()(){{{{中略中略中略}}}}中略 }
class Test02 extends Test01{
int data02;
void void void
void test_functest_functest_func01test_func0101((((int01 intint j)int j)j){{{{中略j) 中略中略}}}}中略 }
メソッドのオーバーロード
dt01(生成されたインスタンス)
data02;
data01;
• test_func01();
Test01
• test_func01(int);
サブクラスの方で、
スーパークラスと同じ名前、
異なる引数の
メソッドを定義することで、
メソッドのオーバーロードが可能
どちらが使われるかは、
引数で判断される
42/33
コンストラクタ
サブクラスのコンストラクタで初期化されなかった、スー パークラスから継承した変数は、スーパークラスの引 数無しのコンストラクタで初期化される。
スーパークラスの引数がある場合のコンストラクタを呼 び出したいときは、明示的に呼び出す必要がある。
呼び出し方は、
とする。これは、サブクラスのコンストラクタの
1
行目に 書く必要がある。super(
引数)
super(
引数)
43/33
例 その 1 : 引数無し
class Test01{
int value01a;
Test01(){
value01a=10;
}
Test01(int a){
value01a=a*100;
} }
class Test02 extends Test01{
int value02a;
Test02(){
value02a=20;
}
Test02(int a, int b){
super(a);
value02a=b*1000;
} }
public class Sample05a{
public static void main(String[] args){
Test02 dt01 = new Test02();
System.out.println(dt01.value01a);
System.out.println(dt01.value02a);
} }
これを、
実行 これも、
実行
value02aしか 初期化してない
44/33
例 その 2 : 引数有り
class Test01{
int value01a;
Test01(){
value01a=10;
}
Test01(int a){
value01a=a*100;
} }
class Test02 extends Test01{
int value02a;
Test02(){
value02a=20;
}
Test02(int a, int b){
super(a);
value02a=b*1000;
} }
public class Sample05b{
public static void main(String[] args){
Test02 dt01 = new Test02(10);
System.out.println(dt01.value01a);
System.out.println(dt01.value02a);
} }
super(a)は、
これを実行
これを、
実行 1行目に 書く
45/33
例 その 3 : super なし
class Test01{
int value01a;
Test01(){
value01a=10;
}
Test01(int a){
value01a=a*100;
} }
class Test02 extends Test01{
int value02a;
Test02(){
value02a=20;
}
Test02(int a, int b){
value02a=b*1000;
} }
public class Sample05c{
public static void main(String[] args){
Test02 dt01 = new Test02(10);
System.out.println(dt01.value01a);
System.out.println(dt01.value02a);
} }
これを、
実行。
これも、
実行
value02aしか 初期化してない