オブジェクト指向: 特殊なクラス
クラス定義部分に直接アクセスし、インスタンス化時に作成(複写)されない。
静的クラス、静的インスタンス変数、静的メソッドがある。
スタティック領域にデータがあり、クラスから作成した複数のインスタンスで値を共有できる。
def normal_method:
@staticmethod
def static_method:
実行
MyClass.static_method()
{
public int member { set; get; }
public void Action() { }
}
public class StaticMember
{
public static int member { set; get; }
public static void Action() { }
}
public static class StaticClass
{
public static int member { set; get; }
public static void Action() { }
}
public void main()
{
NormalClass normalClass = new NormalClass();
normalClass.member = 10;
normalClass.Action();
//↓インスタンス無しでクラスを利用できる
StaticMember.member = 10;
StaticMember.Action();
StaticMember myMenber = new StaticMember();
//↓エラー。インスタンスを作成できない。
StaticClass myStatic = new StaticClass();
myStatic.member = 10;
myStatic.Action();
//↓OK。
StaticClass.member = 10;
StaticClass.Action();
}
{
private:
static int myStaInt;
public:
MyClass();
static int fnStaFunc();
};
MyClass::MyClass()
{
this->myStaInt += 1;
return;
}
static int MyClass::fnStaFunc()
{
静的メソッド内でthis(インスタンスを表す)を使用できない。
this->myStaInt += 10;
myStaInt += 10;
return myStaInt;
};
int MyClass::myStaInt = 0;
int _tmain(int argc, _TCHAR* argv[])
{
int ret = 0;
ret = MyClass::fnStaFunc();
ret:10(myStaInt:10)
MyClass *myClass1 = new MyClass();
myStaInt:11
MyClass *myClass2 = new MyClass();
myStaInt:12
MyClass *myClass3 = new MyClass();
myStaInt:13
ret = MyClass::fnStaFunc();
ret:23(myStaInt:23)
return 0;
}
Private _member As Integer
Public Property member As Integer
略
End Property
Public Sub Action()
~
End Sub
End Class
Public Class SharedMember
Private Shared _member As Integer
Public Shared Property member As Integer
略
End Property
Public Shared Sub Action()
~
End Sub
End Class
‘↓エラー
Public Shared Class SharedClass
~
End Class
Public Sub myForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim myNormal As New NormalClass()
myNormal.member = 10
myNormal.Action()
‘インスタンス無しでクラスを利用できる。
SharedMember.member = 10
SharedMember.Action()
Dim myMember As New SharedMember()
End Sub
private int instanceMember;
private static int staticMember;
public void instanceMethod()
{
System.out.println(instanceMember);
}
static public int staticMethod1()
{
return staticMember;
}
static public int staticMethod2()
{
return instanceMember;
⇒ エラー。
スタティックメソッドはインスタンス変数にはアクセスできない。
this.instanceMember、this.staticMemberも×
thisはインスタンスを指す為、静的メソッド内では使用禁止
}
}
public class MyClass {
public static void main(String[] args) {
SubClass sub = new SubClass();
sub.instanceMethod();
//インスタンスを作成せず、直接staticメソッドを実行
SubClass.staticMember = 5;
int ret1 = SubClass.staticMethod1();
//インスタンスを作成せず、直接staticメソッドを実行
int ret2 = SubClass.staticMethod2();
}
}
print(MyClass::$myVal);
→aaa
MyClass::Method();
静的メソッド呼び出し時は「$」は付けない
→aaa
public class MyClass{
public static $myVal;
public static function Method(){
print(“aaa”);
}
}
MyClass::Method();
→aaa
class MyClass{
private static $_myVal;
public static function GetValue()
{
return self::$_myVal;
}
public static function Method(){
静的メソッド内からクラス内静的プロパティを呼び出し
self::$_myVal = “aaa”;
静的メソッド内からクラス内静的メソッドを呼び出し
print(self::GetValue());
静的メソッド呼び出し時は「$」は付けない
}
}
self::とstatic::
class ParentClass
{
public static function static_method() {
echo ‘ParentClass’, PHP_EOL;
}
public function parent_method() {
static::static_method();
self::static_method();
}
}
class ChildClass extends ParentClass
{
public static function static_method() {
echo ‘ChildClass’, PHP_EOL;
}
public function child_method() {
static::static_method();
self::static_method();
}
}
ParentClass::static_method();
→ ParentClass
ChildClass::static_method();
→ ChildClass
$parent = new ParentClass();
$parent->parent_method();
→ ParentClass
→ ParentClass
$child = new ChildClass();
$child->child_method();
→ ChildClass
→ ChildClass
$child = new ChildClass();
$child->parent_method();
→ ChildClass
※static::static_method()
「static::」=実行時のclass(ChildClass)が呼ばれる
→ ParentClass
※self::static_method();
「self::」=定義時のclass(ParentClass)が呼ばれる
拡張メソッド
静的クラスに作成する、宣言無く使用できるメソッド
{
public static void myMethod(this string prm)
{
Console.WriteLine(prm);
}
}
myExtension.myMethod(@”aaa”);
→aaa
@”bbb”.myMethod();
→bbb
※拡張メソッドではクラス名を省略できる
LINQの拡張
LINQに関しては「LINQ」参照
{
public int Id { get; set; }
public string Name { get; set; }
}
class Persons : List<Person> { }
static class PersonExtension
{
Whereの拡張メソッド
public static Persons Where(this Persons self, Func<Person, bool> predicate)
{
var result = new Persons();
foreach (var p in self)
{
if (predicate(p)) result.Add(item: p);
}
return result;
}
}
class Program
{
static void Main(string[] args)
{
var p = new Persons();
p.Add(new Person() { Id = 1, Name = “C#” });
p.Add(new Person() { Id = 2, Name = “VB.NET” });
p.Add(new Person() { Id = 3, Name = “Java” });
p.Add(new Person() { Id = 4, Name = “PHP” });
IEnumerable.Whereでなく、拡張メソッドWhereを呼び出し
var ary1 = p.Where(x => x.Id > 2).Select(x => x.Name).ToArray();
IEnumerable.Whereを呼び出し
var ary2 = p.AsEnumerable().Where(x => x.Id > 2).Select(x => x.Name).ToArray();
}
}
ローカルクラス
メソッド内でクラスを定義
class Local {
public void sayHello() {
System.out.println(“HelloWorld”);
}
}
ローカルクラスのメソッドを実行
new Local().sayHello();
}
public static void main(String[] args) {
メソッド内でインターフェースを実装したクラスを定義
class Local implements Runnable {
@Override
public void run() {
System.out.println(“HelloLambda”);
}
}
ローカルクラスのメソッドを実行
new Local().run();
}
匿名クラス
var anonymous = new { Name = “Yone”, Age = 35 };
Console.WriteLine(value: anonymous.Name + “(” + anonymous.Age + “)”);
⇒ Yone(35)
ASP.NET MVC ビューヘルパー(「ASP.NET MVC HTMLヘルパー」参照)、やLINQtoEntity(「LINQtoEntity」参照)で利用する
Dim anonymous = New With { .Name = “Yone” , .Age = 35 }
Console.WriteLine(value:=anonymous.Name & “(” & anonymous.Age & “)”)
⇒ Yone(35)
public void method(){
Thread c = new Thread(){
public void run(){System.out.println(“thread start”);}
};
c.run();
インスタンス化と同時に実行
new Thread(){
public void run(){System.out.println(“thread start”);}
}.run();
}
public void method(){
new A(){
public void run(){System.out.println(“thread start”);}
}.run();
エラー:クラスAが無いから
ローカルクラス
class A{};
new A(){
public void run(){System.out.println(“thread start”);}
}.run();
OK
}
インターフェースを実装したローカルクラスを省略形で定義
public static void main(String[] args) {
メソッド内でインターフェースを実装したローカルクラスを定義 ※省略形
Runnable run = new Runnable() {
@Override
public void run() {
System.out.println(“Hello Lambda”);
}
};
メソッド内でインターフェースを実装したローカルクラスを実行
run.run();
}
インターフェースを実装したローカルクラスをラムダ式で定義
Runnable run = () -> { System.out.println(“Hello Lambda”); };
run.run();
ラムダ式については「プログラム言語 ラムダ式」参照
フレンドクラス/フレンド関数
class MyClass{
private:
int myInt;
public:
MyClass(int prm){ this->myInt = prm; };
MyFriendには自身のインスタンス変数へのアクセスを許可
friend class MyFriend;
};
class MyFriend
{
public:
int Get(MyClass prmClass)
{
本来アクセスできないMyClassのインスタンス変数にアクセスする
return prmClass.myInt;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyClass myClass(5);
フレンドクラスであるMyFriendは、
本来アクセスできないMyClassのインスタンス変数にアクセスできる
int ret = (new MyFriend->Get(myClass) ;
ret:5
return 0;
}
フレンド関数
class MyClass{
private:
int myInt;
public:
MyClass(int prm){ this->myInt = prm; };
friend int Get();
friend int Get(MyClass m);
};
int Get()
{
return 5;
}
int Get(MyClass m)
{
return m.myInt;
}
int _tmain(int argc, _TCHAR* argv[])
{
int ret;
MyClass *myClass = new MyClass(10);
ret = Get();
ret:5
本来アクセスできないMyClassのインスタンス変数にアクセスできる
ret = Get(*myClass);
ret:10
return 0;
}
メンバークラス/ローカルクラス
public class Test {
public void method(){
Child c = new Child();
c.method();
}
private class Child extends Test{
public void method(){System.out.println(“inner”);}
}
}
ローカルクラス
public void method(){
class Child{
private void method(){System.out.println(“local”);}
}
Child c = new Child();
c.method();
}
仮想基本クラス
基底クラスのメンバーを派生クラスにおいて重複して継承してしまう問題を回避する為のクラス
多重継承については「オブジェクト指向: 継承/多重継承」参照
※基底クラス
class Parent
{
protected:
int myIntP;
public:
Parent(int prm = 10){ this->myIntP = prm; };
virtual void ShowData() = 0;
};
※派生クラス1
通常継承
class Child1 : public Parent
基底クラスを仮想基本クラスとして継承
class Child1 : public virtual Parent
{
public:
Child1(int prm = 20){ this->myIntP = prm; };
void ShowData();
};
void Child1::ShowData()
{
std::cout << this->myIntP << ‘\n’;
}
※派生クラス2
通常継承
class Child2 : public Parent
基底クラスを仮想基本クラスとして継承
class Child2 : public virtual Parent
{
public:
Child2(int prm = 30){ this->myIntP = prm; };
void ShowData();
};
void Child2::ShowData()
{
std::cout << this->myIntP << ‘\n’;
}
※派生クラス1、2を多重継承
class GrandChild : public Child1, public Child2
{
public:
通常継承時
GrandChild(int prm = 40){ this->myIntP = prm; };
※コンパイルエラー:myIntPはChild1、Child2の両方にあるので曖昧
基底クラスを仮想基本クラスとして継承した場合
GrandChild(int prm = 40){ this->myIntP = prm; };
※OK:myIntPは基底クラスを参照する。
void ShowData();
};
void GrandChild::ShowData()
{
通常継承時
std::cout << this->myIntP << ‘\n’;
※コンパイルエラー:myIntPはChild1、Child2の両方にあるので曖昧
基底クラスを仮想基本クラスとして継承した場合
std::cout << this->myIntP << ‘\n’;
※OK:myIntPは基底クラスを参照する。
}