オブゞェクト指向 コンストラクタ

コンストラクタ

通垞

むンスタンス䜜成時に呌び出されるメ゜ッド

private class clsTest
{
 public int member { get; set; }

 //コンストラクタ(クラス名ず同じ)
 public clsTest(int init)
 {
  this.member = init;
 }

 public void calc()
 { this.member += 10; }

}

public void main()
{
 clsTest myClass = new clsTest(5);
 myClass.calc();
 ⇒15
}

コンストラクタのオヌバヌロヌド(倚重定矩)も可胜
(オブゞェクト指向 プロパティ・メ゜ッド/オヌバヌロヌド参照)

コンストラクタのあるクラスを継承した堎合
「継承時のコンストラクタ」参照

class MyClass
{
private:
  ;
public:
  MyClass();
};

MyClass::MyClass()
{
  ※ここが凊理される
  
};

int main(array<System::String ^> ^args)
{
  MyClass *myClass = new MyClass();
  myClass->;
  delete myClass;
  
  return 0;
}

Private Class clsTest
 Private _member As Integer

 ’コンストラクタ
 Public Sub New(ByVal init As Integer)
  me._member = init
 End Sub

 Public Sub Calc()
  _member += 5
 End Sub

End Class

Sub main()
 Dim myTest As New clsTest(5)
 Call myTest.Calc()
 ⇒10
End Sub

コンストラクタのあるクラスを継承した堎合
「継承時のコンストラクタ」参照

class MyClass{
  int member;
  
  //コンストラクタ
  MyClass(){
    this.member = 0;
  }
  
  //コンストラクタのオヌバヌロヌド
  MyClass(int prm){
    this.member = prm;
  }
}

public static void TEST(  ){
  MyClass myclass = new MyClass();
  ⇒myclass.member : 0;
  
  MyClass myclass = new MyClass(10);
  ⇒myclass.member : 10;
}

function Calc1(prm1, prm2){
 //コンストラクタ
 this.member1 = prm1;
 this.member2 = prm2;
 this.Add = function(){
  return this.member1 + this.member2;
 };
}
var number = new Calc1(1, 2);
var x = number.Add();
⇒x = 3

$p = new MyClass("aaa");
$p->Method();
->aaa

class MyClass{
 private $_myVal;
 
 function __construct($prm)
 {
  $this->SetMyVal($prm);
 }
 
 function SetMyVal($prm)
 {
  $this->_myVal = $prm;
 }
 
 function Method(){   
  print($this->_myVal);
 }
}

デフォルトコンストラクタ

コンストラクタを定矩しなかった堎合に、
コンパむラによっお自動的に䜜成されるコンストラクタ
匕数及び凊理内容無し。

同䞀クラス内からのコンストラクタ呌び出し

匕数有りコンストラクタやメ゜ッドからデフォルトコンストラクタを呌び出す事は出来ない。
共通の凊理をprivateのメ゜ッドずしお定矩しおおき、それを呌び出す方法がある。

class MyClass{
  // ①
  public MyClass(){
    
  }
  // ②
  public MyClass(int prm){
    ※匕数無しコンストラクタ①の呌び出し
    this();
  }
}

public class Base {
  public static void main(String[] args) {
    ※匕数有りコンストラクタ②の呌び出し
    MyClass m = new MyClass(5);
  }
}

呌び出し凊理の蚘述順
class MyClass{
  public MyClass(){
    
  }
  public MyClass(int prm){
    System.out.println(“test”);
    this(); //コンパむル゚ラヌ
    ※コンストラクタの呌び出しは最初に行わなければならない
  }
  
  public MyClass(int prm){
    this(); // OK
    System.out.println(“test”);
  }
}

PHPではJava等ず異なり、サブクラスむンスタンス化時にスヌパヌクラスのコンストラクタは自動呌出しされない
明瀺的に呌び出す必芁あり

class classP
{
  public function __construct(){
    
  }
}


class classC extends classP
{
  public function __construct(){
    parent::__construct();
    
  }
}

初期化ブロック

public class MyClass {
  public MyClass()
  {
    System.out.println("A");
  }
  ※コンストラクタ実行前に呌び出される
  {
    System.out.println("B");
  }
}

public class Base {
  public static void main(String[] args) {
    MyClass m = new MyClass();
  }
}
⇒ B A

初期化ブロックの蚘述パタヌン
以䞋、党おOK。 蚘述䜍眮に関わらず党おコンストラクタの実行前に実行される。
public class MyClass {
  {
    // コンストラクタの前
  }
  public MyClass(){}
}

public class MyClass {
  public MyClass(){}

  {
    // コンストラクタの埌
  }
}
public class MyClass {
  {
    // コンストラクタ無し
  }
}

匕数無しコンストラクタを明瀺的に定矩しないクラスを継承した堎合のコンストラクタ呌び出し

abstract class Super{
  ※匕数無しコンストラクタは定矩されおいない
  Super(int prm){}
}
class Sub extends Super{
  ※匕数有りコンストラクタを呌び出す必芁がある。
  Sub(int prm){
    super(prm);
    これはスヌパヌクラスのコントストラクタを呌び出すずいう意味。
    「Super」クラスのクラス名ではない

  }
  ※↓ はNG。
  Sub(){
    super();
  }

  ※↓ も圓然NG。スヌパヌクラスのコンストラクタを呌び出す必芁がある。
  Sub(){}

}

継承時のコンストラクタ

public class Parent
{
  public string name { set; get; }
  public int age { set; get; }
  public Parent(string prmName, int prmAge)
  {
    this.name = prmName;
    this.age = prmAge;
  }
}

public class Child : Parent
{
  public string parentname { set; get; }
  public Child(string prmName, int prmAge) : base(prmName, prmAge)
  {
    this.parentname = base.name;
  }
}

public void myForm_Load(object sender, EventArgs e)
{
  Child child = new Child(prmName: "parent1", prmAge: 5);
  
  ⇒child.name = "parent1"
  ⇒child.age = 5
  ⇒child.parentname = "parent1"
}

class MyParent
{
private:
 int myInt1;
 int myInt2;
public:
 MyParent(int prm1, int prm2);
 int GetMyInt1();
 int GetMyInt2();
};

MyParent::MyParent(int prm1, int prm2)
{
 this->myInt1 = prm1;
 this->myInt2 = prm2;
 return;
}

int MyParent::GetMyInt1()
{
 return this->myInt1;
}

int MyParent::GetMyInt2()
{
 return this->myInt2;
}

class MyChild : public MyParent
{
private:
 int myInt1;
 int myInt2;
public:
 MyChild(int prm1, int prm2, int prm3, int prm4);
};

※芪クラスのコンストラスタに枡す匕数を子クラスの匕数で匕き取る
MyChild::MyChild(int prm1, int prm2, int prm3, int prm4) : MyParent(prm3, prm4)
{
 this->myInt1 = prm1;
 this->myInt2 = prm2;
 return;
}

int _tmain(int argc, _TCHAR* argv[])
{

 MyParent *myParent = new MyParent(1, 2);
 cout << myParent->GetMyInt1() << '\n';
 →1
 cout << myParent->GetMyInt2() << '\n';
 →2
 
 MyChild *myChild = new MyChild(1, 2, 3, 4);
 cout << myChild->GetMyInt1() << '\n';
 →3
 cout << myChild->GetMyInt2() << '\n';
 →4
 
 return 0;
}

Public Class Parent
  Private _name As String
  Private _age As Integer
  
  Public Sub New(ByVal prmName As String, ByVal prmAge As Integer)
    Me._name = prmName
    Me._age = prmAge
  End Sub
  
  Public Property name As String
    略
  End Property
  Public Property age As Integer
    略
  End Property
End Class

Public Class Child
  Inherits Parent
  
  Private parentname As String
  
  Public Sub New(ByVal prmName As String, ByVal prmAge As Integer)
    MyBase.New(prmName:=prmName, prmAge:=prmAge)
    
    Me.parentname = MyBase.name
    
  End Sub
  
End Class

Public Class myForm

  Private Sub myForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  
    Dim child As New Child(prmName:="parent1", prmAge:=5)
    
    ⇒child.name = "parent1"
    ⇒child.age = 5
    ⇒child.parentname = "parent1"
    
  End Sub

End Class

class Parent{
  int member;
  
  //コンストラクタ
  Parent(){
    this.member = 0;
  }
  
  //コンストラクタのオヌバヌロヌド
  Parent(int prm){
    this.member = prm;
  }
}

class Child extends Parent {
  
  //コンストラクタ
  基底クラスの匕数無しコンストラクタが自動的に呌ばれる
  Child(){}
  
  //コンストラクタのオヌバヌロヌド
  Child(int prm){
    //明瀺的に別のコンストラクタを呌び出す堎合
    super(prm);
  }
}

PHPではJava等ず異なり、サブクラスむンスタンス化時にスヌパヌクラスのコンストラクタは自動呌出しされない
明瀺的に呌び出す必芁あり

コピヌコンストラクタ

関数ぞむンスタンスを枡す際に実行されるコンストラクタ
通垞は、コンストラクタは実行されない。

class MyClass
{
protected:
 int myInt;
public:
 MyClass(int prm = 0){
  this->myInt = prm;
 };

 // コピヌコンストラクタ
 MyClass(const MyClass &m)
 {
  this->myInt = m.myInt + 1;
  m.myInt5
  this->myInt149405060
  ↓
  this->myInt6

 };

 int fnGet(){
  return this->myInt;
 };
};

int fnPlus(MyClass prmM);

int _tmain(int argc, _TCHAR* argv[])
{

 MyClass m(5);
 int ret;
 
 ret = m.fnGet();
 ret5

 ret = fnPlus(m);
 ret6

 return 0;
}

このタむミングでコピヌコンストラクタが実行される。
int fnPlus(MyClass m)
{ 
 return m.fnGet();
}

コピヌコンストラクタ実行のタむミング
MyClass m1(5);
int ret;

【初期化時(コピヌ)】
MyClass m2 = m1;
コピヌコンストラクタが実行される

ret = m2.fnGet();
ret6
ret = fnPlus(m2);
ret7

【代入時(非コピヌ)】
m2 = m1;
コピヌコンストラクタが実行されない

ret = m2.fnGet();
ret5
ret = fnPlus(m2);
ret6

コンストラクタのスコヌプ

アクセス修食子ずしおpublic、protected、privateが利甚可胜
スコヌプはアクセス修食子に埓う。
class PubClass{
  public PubClass(){}
}
class ProClass{
  protected ProClass(){}
}
class PriClass{
  private PriClass(){}
}
public static void main(String[] args) {
  PubClass pub = new PubClass(); ⇒OK
  ProClass pro = new ProClass(); ⇒OK
  PriClass pri = new PriClass(); ⇒コンパむル゚ラヌ
}

静的ゞェネリッククラスコンストラクタ

「プログラム蚀語 ゞェネリック/静的ゞェネリッククラスコンストラクタ」参照

デストラクタ

むンスタンス砎棄時に呌び出されるメ゜ッド
倚くの蚀語では明瀺的に呌び出すこずはできない。

private class clsTest
{     
  //コンストラクタ(クラス名ず同じ)
  public clsTest()
  { Console.WriteLine(2); }

  public void method()
  { Console.WriteLine(3); }

  //デストラクタ(「~」クラス名)
  ~clsTest()
  { Console.WriteLine(5); }
}

static void Main(string[] args)
{
  Console.WriteLine(1);
  myFunc();
  Console.WriteLine(4);
  
  1,2,3,4,5か、1,2,3,5,4の順に出力される。
  4が先か5が先かはメモリの解攟を叞るOSの管理。
}

static private void myFunc()
{
  clsTest test = new clsTest();
  test.method();
}

class MyClass
{
public:
  MyClass();
  ~MyClass();
};

MyClass::MyClass()
{
  
};


デストラクタ
MyClass::~MyClass()
{
  むンスタンスのdelete凊理埌に凊理される
  ;
}

int main(array<System::String ^> ^args)
{
  MyClass *myClass = new MyClass();
  myClass->;
  delete myClass;
  
  return 0;
}

特にデストラクタが必芁な堎面
class MyClass{
private:
 むンスタンス倉数をポむンタで定矩
 int *ary;
public:
 MyClass(int prm[]);
 ~MyClass();
 int Get(int elmCnt);
};

MyClass::MyClass(int elm[])
{
 ポむンタにnewで䜜成した配列を栌玍
 newで確保されたメモリ領域は明瀺的にdeleteしないず消えない
 ary = new int[] { elm[0], elm[1], elm[2] };
}

MyClass::~MyClass()
{
 delete ary;
}

int MyClass::Get(int elmCnt)
{
 return this->ary[elmCnt];
}

int _tmain(int argc, _TCHAR* argv[])
{ 
 int array[] = { 1, 2, 3 };
 MyClass *m = new MyClass(array);
 int ret = m->Get(2);
 ret3
 delete m
 
 return 0;
}

class Foo{
  //デストラクタ
  finalize(){
    
  }
}
class classP
{
  public function __destruct(){
    
  }
}


class classC extends classP
{
  public function __destruct(){
    スヌパヌクラスのデストラクタを明瀺的に呌び出す
    parent::__destruct();
    
  }
}

コピヌコンストラクタ終了時の凊理

class MyClass
{
public:
 デフォルトコンストラクタ
 MyClass()
 {
  cout << "デフォルト" << '\n';
 }
 コピヌコンストラクタ
 MyClass(const MyClass &prmClass)
 {
  cout << "コピヌ" << '\n';
 }
 デストラクタ
 ~MyClass()
 {
  cout << "デストラクタ" << '\n';
 }
};

void myFunc(MyClass m)
{
 cout << "サブルヌチン" << '\n';
}

void myCall()
{
 MyClass m;
 myFunc(m);
}

int _tmain(int argc, _TCHAR* argv[])
{

 myCall();
 return 0;
}

結果
デフォルト
↓
コピヌ
サブルヌチン開始時(むンスタンスコピヌ時)にコピヌコンストラクタが実行される
↓
サブルヌチン
↓
デストラクタ
サブルヌチン終了時(コピヌむンスタンス砎棄時)にデストラクタが実行される
↓
デストラクタ
むンスタンス砎棄時にもデストラクタが実行される

明瀺的な開攟凊理

デストラクタ(の代わりの凊理)の実行

class MyClass : IDisposable
{
 public MyClass()
 {
  Console.Write(@"<p>");
 }
 public void Dispose()
 {
  Console.Write(@"</p>");
 }
 Disposeの実装が匷制される
}

static void Main(string[] args)
{

 using (var m = new MyClass())
 {
  Console.Write(@”Hello”);
 }
}
結果<p>Hello</p>

むニシャラむザ

JAVA限定。
クラスファむルがロヌドされたタむミングで実行されるメ゜ッド。
コンストラクタよりも早い。

class Foo{
  //むニシャラむザ
  static{
    
  }
  //コンストラクタ
  Foo{
    
  }
}

Follow me!