🔥

プログラミング自主学習 19日目 コンストラクタ・this /Class化/Instance化/継承

2023/06/15に公開

コンストラクタ・this

コンストラクタは、インスタンス(オブジェクト)を生成するための特別なメソッドである。
コンストラクタはクラスと同じ名称であり、戻り値を持っていない。

Print p1 = new Print();
CLASS              CONSTRUCTOR

また、初期状態を設定することで、ヒューマンエラーや無駄を減らすことができる。
例えば、FileWriterの場合、

「インスタンス化をする際に、必ず修正するファイルの名前を指定しなければインスタンス化しない。」という条件などをコンストラクタを定義することにより設定することができる。

public class MyOOP {
 public static void main(String[] args) {
     
   Print p1 = new Print();  
   p1.delimiter = "----";  
   p1.A();
   p1.A();
   p1.B();
   p1.B();

   Print p2 = new Print();
   p2.delimiter = "****";
   p2.A();
   p2.A();
   p2.B();
   p2.B();

   p1.A();
   p2.A();
   p1.A();
   p2.A();

  }

}

インスタンスを生成時に、必ずdelimiterを入れなければ生成されないという条件を定義してみる。-> p1.delimiter = "----";

public class MyOOP {
 public static void main(String[] args) {
     
   Print p1 = new Print("----");   
   p1.A();
   p1.A();
   p1.B();
   p1.B();

   Print p2 = new Print("****");
   p2.A();
   p2.A();
   p2.B();
   p2.B();

   p1.A();
   p2.A();
   p1.A();
   p2.A();

  }

}
 Class Print{
   public String delimiter = "";
           public Print(String delimiter){            <- CONSTRUCTOR 
           this.delimiter=delimiter;       (区別する必要がある。)  
          }
           public void A() {
                      System.out.println(this.delimiter);
                      System.out.println("A");
                      System.out.println("A");
          }

           public void B() {
                      System.out.println(this.delimiter);
                      System.out.println("B");
                      System.out.println("B");
          }

this.はインスタンスの変数を指す特別な名前だ。

Class化

public class AccountingApp {

  public static double valueOfSupply;
  .
  .
  .
  public static double vatRate = 0.1;
  .
  .
  .
  public static double getVAT() {
     return valueOfSupply*vatRate;
  }
 .
 .
 .
 .
  public static double getTotal() {
     return valueOfSupply + getVAT();
  }
  .
  .
  .

  public static void main(String[] args) {
  valueOfSupply = 10000.0;
  System.out.println("Value of supply: " +valueOfSupply);
  System.out.println("VAT: " +getVAT());
  System.out.println("Total: " +getTotal());
  }

}

先日、メッソド化を通してまとめたコードである。
コチラの中に数千万のメッソドが混ざていると仮定し、クラス化をしてまとめてみる。

class Accounting{
 public static double valueOfSupply;
 public static double vatRate = 0.1;
 public static double getVAT() {
 return valueOfSupply*vatRate;
  }

  public static double getTotal() {
     return valueOfSupply + getVAT();
  }
}


public class AccountingApp {

.
.
.
.
.
.
.
.
.
..
.
.


  public static void main(String[] args) {
  Accounting.valueOfSupply = 10000.0;
  System.out.println("Value of supply: " +Accounting.valueOfSupply);
  System.out.println("VAT: " +Accounting.getVAT());
  System.out.println("Total: " +Accounting.getTotal());
  }

}

Instance化

Classの内部状態が変わり続ける状況であれば、インスタンス化をした方が効率が向上する。

<BEFORE>
class Accounting{
 public static double valueOfSupply;
 public static double vatRate = 0.1;
 public static double getVAT() {
 return valueOfSupply*vatRate;
  }

  public static double getTotal() {
     return valueOfSupply + getVAT();
  }
}


public class AccountingApp {

  public static void main(String[] args) {
  Accounting.valueOfSupply = 10000.0;
  System.out.println("Value of supply: " +Accounting.valueOfSupply);
  Accounting.valueOfSupply = 20000.0;
  System.out.println("Value of supply: " +Accounting.valueOfSupply);
 
  Accounting.valueOfSupply = 10000.0;
  System.out.println("VAT: " +Accounting.getVAT());
  Accounting.valueOfSupply = 20000.0;
  System.out.println("VAT: " +Accounting.getVAT());
    
  Accounting.valueOfSupply = 10000.0;
  System.out.println("Total: " +Accounting.getTotal());
  Accounting.valueOfSupply = 20000.0;
  System.out.println("Total: " +Accounting.getTotal());
  }
 } 
<AFTER>
class Accounting{
 
public double valueOfSupply;
public Accounting(double valueOfSupply){
 this.valueOfSupply=valueOfSupply;
 } 
public static double vatRate = 0.1;
 public double getVAT() {
 return valueOfSupply*vatRate;
  }
 public double getTotal() {
     return valueOfSupply + getVAT();
  }
}


public class AccountingApp {

  public static void main(String[] args) {
 
   Accounting a1 = new Accounting(10000.0);
   Accounting a2 = new Accounting(20000.0);
   
   System.out.println("Value of supply: " + a1.valueOfSupply);
   System.out.println("Value of supply: " + a2.valueOfSupply);
   System.out.println("Value of supply: " + a1.getVAT());
   System.out.println("Value of supply: " + a2.getVAT());
   System.out.println("Value of supply: " + a1.getTotal());
   System.out.println("Value of supply: " + a2.getTotal());

  }

}

継承(inheritance)

Classを使用しながら、Classにメッソドを追加したり、修正したい場合がある。
しかし、Java固有のClassや他の人が作成したClassなど、既存のClassを修正することができない。

あるClassをベースにコピーを作成し、修正を行ったとしても、もとのClassにバグがある場合、もちろんもとのClass自体を修正するがあるが、コピーされたClassを全体も修正しなければならない。

例えば、CalというClassをメースにメッソドを追加したClassが100個が存在しているとする。もし、Calのメッソドにバグがあるとする場合、それぞれのコピーされたClass100個を修正する必要が生じる。

このような状況では、継承を活用することで問題を解決することができる。

class Cal3 extends Cal{}


Cal3はCalを継承しており、Calを拡張したメッソドである。

また、スパークラスのメッソドを再定義することもできる。その際は同じ名前のメッソドだとしても技能が変わる。このようにスパークラスの技能を再定義することをOverridingという。

Overriding vs Overloading

Overridingとは、継承したクラスがスパークラスのメッソドを再定義することだ。

Overloadingとは、同じ名前のメッソドだとしてもメッソドの形(パラメータ)が異なれば、共存することだ。

public int sum(int v1, int v2) { return v1+v2; }
public int sum(int v1, int v2, int v3) { return v1+v2+v3; }

Discussion