JAVA-21
●復習
▶️オーバーロード
クラスにない、同じ名前で引数の型や数が違うメソッドを定義すること。同じような機能を持つメソッドであっても引数のデータ型が異なれば別々のメソッドを用意する必要がある。
//同じクラス内の、同じメソッドの名前だが、 引数が異なる。
なので、定義する時に引数を変えれば、それぞれ違うメソッドを呼び出す。
class Student {
void setData(String n){
(中略)
}
void setData(String n, int e, int m){
(中略)
}
▶️オーバーライド
・サブクラスで、スーパークラスのメソッドを再定義すること。
条件は、戻り値の型、メソッド名、引数の型と数が全て同じ場合。
オーバーロード
1つのクラスの中で同じ名前のメソッドを複数定義できること。
オーバーライド
スーパークラスとサブクラスでのメソッドの上書きである。
//スーパークラスPerson2
public class Person2{
private String name;
public void setName(String n){
name = n;
}
public String getName(){
return name;
}
public void display(){
System.out.println("名前:" + name);
}
}
//スーパークラスを継承した、サブクラスStudent2(設計図クラス)
public class Student2 extends Person2{
private int stuNo;
public void setStuNo(int s){
stuNo = s;
}
public void display(){
System.out.println("名前:" + getName());
System.out.println("学籍番号:" + stuNo);
/ }
}
//StuSample2(実行用クラス)
public class StuSample2{
public static void main(String[] args){
Student2 stu = new Student2();
stu.setName("菅原");
stu.setStuNo(1);
stu.display();
}
}
▶️コンストラクタ
オブジェクトの初期化のために使われる特殊なメソッド。
名前がクラス名と同じであり、戻り値を持たないこと(voidを設定)、newクラス名(コンストラクタへの引数)があることが条件。
もし、コンストラクタを定義しなければ、デフォルトコンストラクタ
(引数&処理なし)が生成されることになる。
class Student{
Student(String n){
}
▶️static
class Student{
static int counter = 0;
Student(){
counter ++;
}
static void display(){
System.out.println(counter + "人です");
}
全インスタンス変数が使える
メンバ変数やメソッドを定義する時には、staticを指定する。
クラス名.変数[メソッド]名と書きなおす必要がある。
↑ クラス内で幅を広げることで、カウントする表現を広げる的な??
▶️カプセル化
「アクセス修飾子」でクラス・メンバ変数・メソッドの公開範囲を指定すること
⦅公開範囲⦆
public
同クラス、同パッケージ、サブクラス、その他
protected
同クラス、同パッケージ、サブクラス
(なし)
同クラス、同パッケージ
private
同クラス
メンバ変数は、隠蔽(private)して、
クラスとメソッドは公開(publiv)する設計方針をカプセル化と呼ぶ。
代入前処理ができる、修正範囲を変えやすいというメリットがある。
class Student{
private int score;
public void setScore(int s){
(中略)
score = s;
}
}
○ stu.setScore(80);
× stu.score = 80;
//このように、直接代入をすると、コンパイルエラーが出ることになる。
▶️継承
既存のクラスをもとに変数やメソッドを追加したクラスを作ること。
継承関係にある親クラスをスーパークラス、子クラスをサブクラスという。extendを入れることによって、継承できる。
public class Person{
private String name;
public void setName(String n){
name = n;
}
public void display(){
System.out.println("名前:" + name);
}
}
//extendsを入れることによって、クラスを継承できる!!
public class Student extends Person{
private int stuNo;
public void setStuNo(int s){
stuNo = s;
}
public void displayStuNo(){
System.out.println("学籍番号:" + stuNo);
}
}
public class StuSample{
public static void main(String[] args){
Student stu = new Student();
// スーパークラスのメソッド
stu.setName("菅原");
stu.display();
// サブクラスのメソッド
stu.setStuNo(1);
stu.displayStuNo();
}
}
▶️this とsuper
this とsuperによるメソッド・メソッドの呼び出し
this.~ = 自オブジェクトの〜
super.~ = スーパークラスの〜
プログラムの処理を再び書く必要がない。引数名を考えなくて良い。
public class Person3{
private String name;
public Person3(String name){
this.name = name;
}
public void display(){
System.out.println("名前:" + name);
}
}
this とsuperによるコンストラクタの呼び出し
this()~ = 自オブジェクトの〜
super()~ = スーパークラスの〜
これらは、コンストラクタ内の先頭に記述するようにする。
なければ、自動的にsuper();が設定されることになる。
●勉強
(継承、オーバーライド、this &superキー復習)
▶️演習問題1
では、Taxi1クラスを定義していこう。
Taxi1クラスは、自動車を管理するCar1クラスを継承している。
まず、Car1クラスのコードがこちら。
//参考1
public class Car1{
private int no;
public void setNo(int n){
no = n;
}
public void display(){
System.out.println("ナンバーは" + no + "です");
}
}
//参考2
public class DriveTaxi1{
public static void main(String[] args){
Taxi1 t1 = new Taxi1();
t1.setNo(2525);
t1.start();
t1.run();
t1.display();
}
}
これを継承するのでextendsが必要になるはず。
//自分のコード
public class Taxi1 extends Car1{
//タクシーの料金(メンバ変数)
private int price;
//変数priceに420を代入する。(メソッド)
public void start(){
price = 420;
}
//変数priceに80を加算する。(メソッド)
public void run(){
price += 80;
}
//変数priceの値を表示する。(メソッド)
public void display(){
System.out.println("料金は" + price + "です");
}
}
▶️回答1
継承するということがわかっているか
//回答例
public class Taxi1 extends Car1{
private int price;
public void start(){
price = 420;
}
public void run(){
price = price + 80;
}
public void display(){
System.out.println("料金は" + price + "円です");
}
}
▶️演習問題2
//Taxi1クラス
public class Taxi1 extends Car1{
private int price;
public void start(){
price = 420;
}
public void run(){
price = price + 80;
}
public void display(){
System.out.println("料金は" + price + "円です");
}
}
//参考用クラス
public class Car2{
private int no;
public Car2(int no){
//このオブジェクトの〜
→メンバ変数へと変換
this.no = no;
}
public void display(){
System.out.println("ナンバーは" + no + "です");
}
}
これより、Taxi2クラスを作る。
//自分のコード
public class Taxi2 extends Car2{
//メンバ変数
private int price;
//変数noに引数を設定する、変数priceに、0を設定する。
public Taxi2(int no){
price = 0;
}
//変数no,priceを引数を設定する。
public Taxi2(int no, int price){
}
//変数priceに420を設定する。
public void start(){
price = 420;
}
//変数priceに80を加算する。
public void run(){
price = price + 80;
}
//変数noと変数priceの値を表示する。
public void display(){
System.out.println("料金は" + price + "円です");
}
}
//実行用クラス
public class DriveTaxi2{
public static void main(String[] args){
Taxi2 t2 = new Taxi2(2525);
t2.start();
t2.run();
t2.display();
}
}
▶️回答2
public class Taxi2 extends Car2{
private int price;
public Taxi2(int no){
this(no, 0);
}
public Taxi2(int no, int price){
super(no);
this.price = price;
}
public void start(){
price = 420;
}
public void run(){
price = price + 80;
}
public void display(){
super.display();
System.out.println("料金は" + price + "円です");
}
}
public class Taxi2 extends Car2{
private int price;
public Taxi2(int no){
//Taxi2のクラス
this(no, 0);
}
public Taxi2(int no, int price){
//スーパークラスのコンストラクトを使いたい
super(no);
//このクラスのコンストラクタを使いたい
this.price = price;
}
public void start(){
price = 420;
}
public void run(){
price = price + 80;
}
public void display(){
//Car2クラスのメソッドを呼び出したいている。
super.display();
System.out.println("料金は" + price + "円です");
}
}
▶️演習問題3
次のプログラムを実行した時にどのように表示されるか。答えなさい。
//プログラム1
class Car{
Car(){
System.out.println("Car()");
}
Car(int no){
System.out.println("Car(int no)");
}
}
//プログラム2
class Taxi extends Car{
Taxi(){
this(9999);
System.out.println("Taxi()");
}
Taxi(int no){
super(no);
System.out.println("Taxi(int no)");
}
Taxi(String no){
System.out.println("Taxi(String no)");
}
}
//プログラム3
class DriveTaxi{
public static void main(String[] args){
Car c = new Car();
System.out.println("-----");
Taxi t1 = new Taxi(2525);
System.out.println("-----");
Taxi t0 = new Taxi();
System.out.println("-----");
Taxi t2 = new Taxi("2525");
}
}
プログラム3を追っていく。
//プログラム3
class DriveTaxi{
public static void main(String[] args){
//コンストラクタcをCarクラスに生成
Car c = new Car();
//-----が表示された後、改行
System.out.println("-----");
//コンストラクタt1を生成、Taxi1クラスに2525の値を代入。
Taxi t1 = new Taxi(2525);
//-----が表示された後、改行
System.out.println("-----");
//コンストラクタt0をTaxiクラスに生成
Taxi t0 = new Taxi();
//-----が表示された後、改行
System.out.println("-----");
//コンストラクタt2を生成、Taxiクラスに"2525"という文字列を代入。
Taxi t2 = new Taxi("2525");
}
}
//プログラム3
class DriveTaxi{
public static void main(String[] args){
/* コンストラクタcをCarクラスに生成
Car(){
System.out.println("Car()");
}となっているので、Car()という文字が表示されるはず。 */
Car c = new Car();
//-----が表示された後、改行
System.out.println("-----");
/*コンストラクタt1を生成、Taxiクラスに2525の値を代入。
Taxi(int no){
super(no);
System.out.println("Taxi(int no)");
}となっているので、まず親クラスのno数値に2525を代入する。親クラスは
Car(int no){
System.out.println("Car(int no)");
}となっているので、"Car(2525)"という文字列が生成される。
また、"Taxi(2525)" という文字列が生成される。*/
Taxi t1 = new Taxi(2525);
//-----が表示された後、改行
System.out.println("-----");
/*コンストラクタt0をTaxiクラスに生成
Taxi(){
this(9999);
System.out.println("Taxi()");
}
this(9999)の部分は、サブクラスのTaxi(9999)であるので、
Taxi(int no){
super(no);
System.out.println("Taxi(int no)");
}より、
Taxi(9999){
super(9999);
System.out.println("Taxi(9999)");
}より、
Car(9999){
System.out.println("Car(9999)");
}より、Car(9999)が表示される。
また、System.out.println("Taxi(int no)");より、
Taxi(9999)が表示される。
さらに、System.out.println("Taxi()");より、
Taxi()が表示される。 */
Taxi t0 = new Taxi();
//-----が表示された後、改行
System.out.println("-----");
/*コンストラクタt2を生成、Taxiクラスに"2525"という文字列を代入。
Taxi("2525")より、"2525"はStringとして考えるので、
Taxi(String no){
System.out.println("Taxi(String no)");
}より、
Taxi("2525"){
System.out.println("Taxi(2525)");
}より、Taxi(2525)が表示される。 */
Taxi t2 = new Taxi("2525");
}
}
まとめると、
//プログラム3まとめ
class DriveTaxi{
public static void main(String[] args){
//"Car()"と表示
Car c = new Car();
//"-----"と表示
System.out.println("-----");
//"Car(2525)"と表示
//"Taxi(2525)" と表示
Taxi t1 = new Taxi(2525);
//"-----"と表示
System.out.println("-----");
//"Car(9999)"が表示
//"Taxi(9999)"が表示
//"Taxi()"が表示
Taxi t0 = new Taxi();
//"-----"が表示
System.out.println("-----");
//"Taxi(2525)"が表示
Taxi t2 = new Taxi("2525");
}
}
よって、コンパイルはおそらく
//コンパイル実行
Car()
-----
Car(2525)
Taxi(2525)
-----
Car(9999)
Taxi(9999)
Taxi()
-----
Taxi(2525)
でしょうか・・・??
▶️回答2
それぞれのコンストラクタを呼び代した時に、どのような順番で呼び出されるかを終えるかがポイントになる。
//コンパイル実行
Car()
-----
Car(int no)
Taxi(int no)
-----
Car(int no)
Taxi(int no)
Taxi()
-----
Car()
Taxi(String no)
super(no);
引数2525をスーパークラスに渡すこと。
this(9999);
そのクラス内のTaxi(int no)が再度呼び出されることになる。
super(9999);
System・・・・
今回重要だったのは、
最初にthis (~)やsuper(~)がない場合は、
「super();」が自動で呼び出されるという動きになる!!
→ Car()が表示されることになる。
今日はここまで!!
●名言
私は自分が死ぬ覚悟ならある。 しかし、私に人を殺す覚悟をさせる大義はどこにもない。 「眼には眼を」で行けば、しまいには全世界が盲目になってしまう。 国の偉大さ、道徳的発展は、その国における動物の扱い方で判る。
プーチンさん、犬の扱い方うまかったのになぁ。