009.4. 静的と動的の違い

過去のブログのアーカイブ
この記事は前身のブログのアーカイブを引き継いだものです. 画像が正しく表示できないなど,コンテンツの表示に問題がある恐れがあります.

オブジェクト思考で大事になってくる考えに動的型と静的型があります。この二つは主に元になっているものがあり、元のものに影響があるかどうかによって変わります。
わかりづらいので例に沿って説明します。

動的について

動的とは、元になるものがある状態で呼び出されるものです。
必ず元になるオブジェクトが存在するので、そのメソッドを実行した結果は、そのオブジェクトに依存します。

動的メソッド

動的メソッドは主に、元になるものがある状態で呼び出されるメソッドです。
このメソッドの特徴は、元になるものに何かしらの影響を及ぼすことです。
サンプルを見てみましょう。

Form ff = new Form();
// ...中略
ff.Close();

この例は、画面上にフォーム(ウィンドウ)を閉じる例です。
Closeメソッドの元になるオブジェクトはff変数。そしてこの命令を実行したことによってffフォームが閉じられる、つまり画面から消えるという影響を及ぼします。
動的メソッドを呼び出す際は以下のようにして呼び出します。

(元になるオブジェクト).メソッド名(パラメータ)

必ず元になるオブジェクトが存在するのが特徴です。

動的変数/動的プロパティ

これは単に元になるオブジェクトのデータを取り出す/格納するというものです。
例を見てみましょう。

Form ff = new Form();
// ... 中略
string str = ff.Text; // ff.Text :: フォームのタイトルを取得/設定する

このコードはフォームのタイトルを取得し、str変数に格納するというコードです。
このように、元になるオブジェクトのデータを取得することができます。そして、元になるオブジェクトが違うといきちんと取り出されるデータも変わってきます。(当たり前ですね)
d1
※v1.Value / v2.Valueが動的変数です。
このように、オブジェクトにより、別々の内容を持っているため、元になるオブジェクトにより、結果が依存するというわけです。

静的について

静的とは元になるものが存在しない状態で呼び出される場合に利用されます。
この特徴はどこからアクセスして同じものを共有されるところにあります。

静的メソッド

静的メソッドが利用されるのは、元になるオブジェクトに対しては影響を及ばさない命令に対して利用されます。
こちらも例を見てみましょう。

string str = "123";
int test = int.Parse(str);
// test => 123

int.Parseは何かしらのオブジェクトから数値型に変換する命令です。
strの中身が”123″なので、それを数値型に変換して123にしています。
しかし、変換されたからといって、strが消滅するわけではなく、数値123が新しく作られます。
このように、元になるオブジェクトに対して影響を及ばさない命令に対しては、静的メソッドがよく使われます。
また、Consoleクラスのように特例もあって、1つのプログラムに対して1つ、または1つのシステムに対して1つしか存在できないオブジェクトに対する命令を静的メソッドが使われる傾向にあります。

静的変数/静的プロパティ

こちらの特徴としては、1度初期化されると、どこからアクセスしても常に同じところを参照します。
そして、元になるオブジェクトを指定しないため、実質グローバル変数のような役割をすることができます。
例を見てみましょう。

public class A {
    public static Value = 0;
}
public Main() {
    A.Value = 10;
    Test();
    // A.Value => 20
}
 public void Test() {
    A.Value = 20;
}

このように、どこからアクセスしても、データを編集することができます。(もちろん、publicやprivateのようなアクセス修飾子も対応しています。)
C#ではC言語のようにグローバル変数は許可されていませんが、このようにクラスに静的変数を定義すれば、実質同じことができます。
d1
※A.Valueが静的変数です。
メモリの中に直接変数が格納されるため、どこからアクセスしようが、常に同じオブジェクトを参照されます。

まとめ

動的は元になるやつがあり、静的は、元になるやつがいりません。

値型の性的変数について

値型はパラメータ等に使用すると常にオブジェクトがコピーされます。詳しくはこの記事を参照
つまり、直接参照しない限り、そのデータは編集されないのです。ここからは当たり前っちゃ当たり前の話なのですが、心配な方はこの先も読んでください。

// Aは構造体(値型)
public struct A {
    public int Value = 10;
}
public class B {
    public static A VVV = new A();
}
public void Main() {
    // Aは値型なのでA.VVVの戻り値はコピーされて変数vに格納される。
    A v = B.VVV;
    v.Value = 20;
    // A.VVVとvは別のオブジェクトである。(コピーされたものだから)
    // v.Value => 20
    // B.VVV.Value => 10
    // B.VVVの中身を直接編集する
    B.VVV.Value = 30;
    // やはりvはB.VVVの中身をコピーされた別オブジェクトなので独立して記録される。
    // B.VVV.Value => 30;
    // v.Value => 20
}

値型はこの点厄介なところもあるので、注意してください。ただ値型の構造体が静的変数になっているケースはそんなに多くないと思いますが…