オブジェクト指向: プロパティ・メソッド
プロパティ
アクセサ
メンバ変数(インスタンス変数)に外部からアクセスすつ為のメソッド
get(set)アクセサ、getter(setter)と呼ばれる。
private int _member1;
public int member1
{
//getアクセサ
get { return this._member1; }
//setアクセサ
valueは宣言不要
set { _member1 = value; }
}
//↑の省略形
public int member2 { get; set; }
public void SubRoutin1(){
~
}
}
public void main()
{
clsParent myParent = new clsParent();
myParent.member1 = 5;
int x = myParent.member1;
myParent.member2 = 10;
int y = myParent.member2;
myParent.SubRoutin1();
}
{
private:
int _member;
public:
int GetMember();
void SetMember(int member);
};
int MyClass::GetMember()
{
return this->_member;
}
void MyClass::SetMember(int member)
{
this->_member = member;
}
int main(array<System::String ^> ^args)
{
MyClass *myClass = new MyClass();
myClass->SetMember(10);
Console::WriteLine(myClass->GetMember());
// →10
delete myClass;
return 0;
}
※Getter/Setterを同名でオーバーロードすると呼び出し側からは使いやすくなる。
「オーバーロード」参照
Dim _Menber As Integer
Public Property Menber As Integer
‘getアクセサ
Get
Return _Member
End Get
‘setアクセサ
Set(ByVal prm As String)
_Member = prm
End Set
End Property
Public Sub SubRoutine()
~
End Sub
End Class
Dim myTest As New clsTest()
myTest.Member = 10
Dim x As Integer = myTest.Member
Call myTest.SubRoutine()
※MyClass.cls
Dim pMyVal As Integer
Dim pMyObj As Object
‘参照(読み取り)専用:データ型
Public Property Get Getter() As Integer
Getter = pMyVal
End Property
‘参照(読み取り)専用:オブジェクト型
Public Property Get Getter() As Object
Set Getter = pMyVal
End Property
‘設定(書き込み)専用:データ型
Public Property Let Letter(ByVal prm As Integer)
pMyVal = prm
※正確には↓ の様に書くが「Let」は省略可能。
Let pMyVal = prm
End Property
‘設定(書き込み)専用:オブジェクト型
Public Property Set Setter(ByVal prm As Object)
Set pMyObj = prm
End Property
‘イニシャライザー
Private Sub Class_Initialize()
Call MsgBox("Initialize()")
End Sub
‘ファイナライザー
Private Sub Class_Terminate()
Call MsgBox("Terminate()")
End Sub
※呼び出し元
Private Sub Form_Load()
Dim myClass As myClass
Set myClass = New myClass
myClass.Letter = 5
Let myClass.Letter = 5
Dim myObj As Object
Set myClass.Setter = myObj
Debug.Print (myClass.Getter)
Set myClass = Nothing
End Sub
private int _member1;
public int member1
{
//getter
get { return this._member1; }
//setter
valueは宣言不要
set { _member1 = value; }
}
public void SubRoutin1(){
~
}
}
public void main()
{
clsParent myParent = new clsParent();
myParent.member1 = 5;
int x = myParent.member1;
myParent.member2 = 10;
int y = myParent.member2;
myParent.SubRoutin1();
}
this.member1 = prm1;
this.member2 = prm2;
}
var number = new Calc1(1, 2);
var x = number.member1 + number.member2;
⇒ x : 3
number.member1 = 10;
number.member2 = 20;
var y = number.member1 + number.member2;
⇒ x : 30
var Calc2 = function(prm1, prm2){
this.member1 = prm1;
this.member2 = prm2;
};
var number = new Calc2(100, 200);
var x = number.member1 + number.member2;
⇒ x : 300
number.member1 = 1000;
number.number2 = 2000;
var y = number.member1 + number.member2;
⇒ y : 3000
$p->SetMyVal("aaa");
$val = $p->GetMyVal
$val:aaa
class MyClass{
private $_myVal;
function SetMyVal($prm)
{
$this->_myVal = $prm;
}
function GetMyVal()
{
return $this->_myVal;
}
}
読み取り・書き込み専用属性
int _member;
public int member{ get; }
int _member;
public int member{ set;}
宣言時、コンストラクタでのみ設定可能なインスタンス変数
(固定値(const)と違い、インスタンス毎に値を変えられる)
public class Test
{
private readonly int member = 5;
public Test(int init)
{
this.member = init;
}
public int Member
{
get { return this.member; }
⇒ OK
set { this.member = value; }
⇒ ビルドエラー
}
}
Public ReadOnly Property Menber As Integer
Get
Return _Member
End Get
End Property
Dim _Menber As Integer
Public WriteOnly Property Menber As Integer
Set(ByVal prm As String)
_Member = prm
End Set
End Property
インデクサ
※インスタンス自身をプロパティとして扱う
public class MyList<T>
{
T[] _list = new T[1000];
public T this[int index]
{
get { return _list[index]; }
set { _list[index] = value; }
}
}
public void Form1_Load(object sender, EventArgs e)
{
MyList<int> myList = new MyList<int>();
for (var i = 0; i < 10; i++)
{
myList[i] = i;
※インスタンスをプロパティとして扱っている
}
}
Public Class MyList(Of T)
Dim _list(1000) As T
//デフォルトのプロパティを宣言
Default Public Property list(ByVal index As Integer) As T
Get
Return _list(index)
End Get
Set(value As T)
_list(index) = value
End Set
End Property
End Class
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim myList As New MyList(Of Integer)
For i As Integer = 0 To 10 Step 1
myList(i) = i
※インスタンスをプロパティとして扱っている
Next i
End Sub
メソッド
クラス内サブルーチン
public宣言する事でクラス外部から呼ばせる事が可能。
{
private int member;
public void SubRoutine(int prm1, int prm2)
{ this.member = prm1 + prm2; }
}
public void main()
{
Parent p = new Parent();
p.SubRoutine(prm1:5, prm2:10);
}
class MyClass
{
private:
int ~;
public:
void sayMember(){
~
}
};
// 外部宣言
class MyClass
{
private:
int ~;
public:
// プロトタイプ宣言
void sayMember();
};
void MyClass::sayMember()
{
~;
}
int main(array<System::String ^> ^args)
{
インスタンスをスタック領域に作成
MyClass myClass
myClass.sayMember();
インスタンスをヒープ領域に作成
MyClass *myClass = new MyClass();
myClass->sayMember();
delete myClass
return 0;
}
※スタック領域/ヒープ領域については、「メモリ管理/ヒープ領域」参照
Private member As Integer
Public Sub SubRoutine(
ByVal prm1 As Integer, _
ByVal prm2 As Integer)
me.member = prm1 + prm2
End Sub
End Class
Public Sub Main()
Dim p As New Parent()
p.SubRoutine(prm1:=5, prm2:=10)
End Sub
this.answer;
this.add = function(prm1, prm2){
this.answer = prm1 + prm2;
};
};
$p->Method();
aaa
class MyClass{
function Method(){
print("aaa");
}
}
オーバーロード
多重定義
引数・戻り値の異なる同名のメソッドを定義する事。
似た機能を同名にする事で直感的に使いやすくなる。
設計時には名前衝突も起こり難い。
{
public int member{ get; set; }
public void SubRoutine(int prm1, int prm2)
{ this.member = prm1 + prm2; }
//オーバーロード(引数が違う)
public void SubRoutine()
{ Console.WriteLine(this.member); }
//オーバーロード(戻り値が違う)
※引数も変える必要あり
public int SubRoutine(int prm1, int prm2, int prm3)
{
return prm1 + prm2 + prm3;
}
}
※Getter/Setterを同名でオーバーロードした例
class MyClass
{
private:
int _member;
public:
int Member();
void Member(int member);
};
int MyClass::Member()
{
return this->_member;
}
void MyClass::Member(int member)
{
this->_member = member;
}
int main(array<System::String ^> ^args)
{
MyClass *myClass = new MyClass();
myClass->Member(10);
Console::WriteLine(myClass->Member());
// →10
delete myClass;
return 0;
}
Private member As Integer
Public Sub SubRoutine(
ByVal prm1 As Integer, _
ByVal prm2 As Integer)
me.member = prm1 + prm2
End Sub
’オーバーロード(引数が違う)
Public Overloads Sub SubRoutine()
Console.WriteLine(me.member)
End Sub
’オーバーロード(引数が違う)
※引数も変える必要あり
Public Overloads Function SubRoutine(
ByVal prm1 As Integer, _
ByVal prm2 As Integer, _
ByVal prm3 As Integer) As Integer
Return prm1 + prm2 + prm3
End Sub
End Class
{
private int member;
public void SubRoutine(int prm1, int prm2)
{ this.member = prm1 + prm2; }
//オーバーロード(引数が違う)
public void SubRoutine()
{ Console.WriteLine(this.member); }
//オーバーロード(戻り値が違う)
※引数も変える必要あり
public int SubRoutine(int prm1, int prm2, int prm3)
{
return prm1 + prm2 + prm3;
}
}
this.answer;
this.add = function(prm1, prm2){
this.answer = prm1 + prm2;
};
};
var Child = function(){};
//継承
Child.prototype = new Parent();
Child.prototype.minus = function(prm){
this.answer -= prm;
};
var child = new Child();
child.add(1,1);
child.minus(1);
⇒this.answer = 1
演算子のオーバーロード
{
int x, y;
public MyClass() { x = y = 0; }
public MyClass(int i, int j) { x = i; y = j; }
public static MyClass operator +(MyClass prm1, MyClass prm2)
{
MyClass result = new MyClass();
result.x = prm1.x + prm2.x;
result.y = prm1.y + prm2.y;
return result;
}
}
class Program
{
static void Main(string[] args)
{
MyClass a = new MyClass(1, 1);
MyClass b = new MyClass(10, 10);
MyClass c = new MyClass();
c = a + b;
c.x:11 c.y:11
+はMyClassとMyClassの値が足されている
}
}
class MyClass
{
int x, y;
public MyClass() { x = y = 0; }
public MyClass(int i, int j) { x = i; y = j; }
public static MyClass operator +(MyClass prmObj, int prmInt)
{
MyClass result = new MyClass();
result.x = prmObj.x + prmInt;
result.y = prmObj.y + prmInt;
return result;
}
}
class Program
{
static void Main(string[] args)
{
MyClass a = new MyClass(1, 1);
MyClass result = new MyClass();
result = a + 5;
result.x:6 result.y:6
+はMyClassとintの値が足されている
}
}
{
private:
int myInt1;
int myInt2;
public:
MyClass(int prm1, int prm2);
void Show();
MyClass operator+(MyClass obj);
};
MyClass::MyClass(int prm1 = 0, int prm2 = 0)
{
this->myInt1 = prm1;
this->myInt2 = prm2;
};
void MyClass::Show()
{
cout << "myInt1:" << this->myInt1 << endl;
cout << "myInt2:" << this->myInt2 << endl;
}
MyClass MyClass::operator+(MyClass obj)
{
MyClass m;
m.myInt1 = this->myInt1 + obj.myInt1;
b.myInt1 + c.myInt2
m.myInt2 = this->myInt2 + obj.myInt2;
b.myInt2 + c.myInt2
return m;
結果をa.myInt1、a.myInt2に格納
インスタンス:mはここで破棄される
}
int _tmain(int argc, _TCHAR* argv[])
{
MyClass a(0, 0);
MyClass b(10, 20);
MyClass c(50, 60);
a = b + c;
オーバーロードした+を利用
bの+関数へcを渡し、結果をaに格納する
a = b.+(c)
a.Show();
→myInt1:60 myInt2:80
return 0;
}
クラス外にオーバーロード演算子を定義
パターン1
class MyClass
{
private:
int myInt;
public:
MyClass(int prm){ this->myInt = prm; };
int Getter(){ return this->myInt; }
};
通常の+演算子をオーバーロード
MyClass operator+(int prmI, MyClass prmM)
{
return MyClass(prmI + prmM.Getter());
}
int _tmain(int argc, _TCHAR* argv[])
{
MyClass a(0);
MyClass b(100);
a = 1000 + b;
オーバーロード+に引数1000とbインスタンスを渡し、結果をaに格納
(なぜか)左側数値が第一引数、右側オブジェクトが第二引数
→a.myInt:1100
return 0;
}
パターン2
MyClass operator+(MyClass m1, MyClass m2)
{
return MyClass(m1.Getter() + m2.Getter());
}
int _tmain(int argc, _TCHAR* argv[])
{
MyClass a(0);
MyClass b(100);
MyClass c(100);
a = b + c;
オーバーロード+に引数:aインスタンスとbインスタンスを渡し、結果をaに格納
(なぜか)左側数値が第一引数、右側オブジェクトが第二引数
→a.myInt:200
return 0;
}
メンバーの追加(JS)
var MyClass = function(){};
MyClass = function(){
this.member1;
};
MyClass = function(){
this.add1 = function(){
this.member1 += 1;
};
};
var myclass = new MyClass();
myclass.member1 = 5;
myclass.add1();
// ⇒ myclass.member1 = 6;
//インスタンスに対してメンバー追加
member.Minus = function(){
return this.member1 – this.member2;
};
number.Minus();
⇒-1000;
var newMember = new Calc2();
newMember.Minus();
//↑ 未定義エラー
インスタンス作成時のメソッドのコピー
全く同じ挙動をするメソッドを全インスタンスにコピーするのはメモリの無駄。
その為、例えばWebシステム用言語JavaScriptではprototype等を用いてメソッドのインスタンスへのコピーを省略する仕様を持つ。
しかしC#ではメソッドはインスタンスにコピーされず、クラスを参照する為のポインタがコピーされるのみ。
クラスのコピー(インスタンス作成)の際の、メソッドに関するメモリ制御を考慮する必要はない。
※プロパティはインスタンス毎に異なる値を持たせる意味はあるが、
全く同じ挙動をするメソッドを全インスタンスにコピーするのはメモリの無駄。
ブラウザの読み込み毎にインスタンスを作成するWEBシステムの特性を考慮し、
メソッドについては通常、以下の機能を用いてメモリーコピーを行わせない。
MyClass.prototype.plus10 = function(number){
this.member1 += 10;
this.member2 += 10;
}
var myclass = new MyClass()
myclass.plus10()
//プロトタイプ定義の別の書き方
MyClass.prototype = {
this.plus10 = function(number){
this.member1 += 10;
this.member2 += 10;
}
}