++C++; // 未確認飛行 C

Google
Web ufcpp.net

静的変数・静的メソッド

目次

キーワード

概要

静的変数(static variable)・静的メソッド(static method)とは、 特定のインスタンスにではなく、クラスに属するメンバ変数やメソッドのことです。 そのため、静的変数のとこをクラス変数とも呼びます。 (クラス変数という呼び名の方が意味合い的には正しいのですが、 C言語から派生したというC#の歴史的な背景のため、静的変数という呼び方をします。) それに対し、通常のメンバ変数のことをインスタンス変数と呼びます。

静的変数・静的の使い方

クラスのメンバ変数やメソッドを定義する際に、 static キーワードを付けることで、 その変数は静的メンバ変数・静的メソッドになります。

static 型名 変数名

静的変数・静的メソッドはクラスごとに唯一つの実体を持ち、すべてのインスタンスの間で共有されます。

例として、人間について考えてみましょう。 この場合、特定のインスタンスとは個人個人のこと、 クラスとは人間という種別そのもののことになるわけですが、 名前や年齢などは各個人ごとに異なりますが、 人という種の学名「Homo sapiens」などのように個体によらない共通のものもあります。 したがって、人間をあらわすPersonというクラスを作成した場合、 name(名前)やage(年齢)といったメンバ変数を作りたい場合はインスタンス変数に、scientificName(学名)などのクラス全体で共有すべき変数を作りたい場合は静的変数にすべきです。 (実際には学名などの普遍な値は定数(const)として定義すべきですが、 ここでは説明のためということでご容赦を。 定数の定義については後ほど説明します。)

class Person
{
  public string name; // 名前。個体ごとに違うので、インスタンス変数に。
  public int age;     // 年齢。同上、インスタンス変数に。

  public static string scientificName;
  // 学名。個体じゃなくて種によって決まるものなので、静的変数に。
}

静的変数はクラスに属する値なので、値を参照するには以下のようにします。

Person p = new Person()

p.name = "野上冴子"; // インスタンス変数は [インスタンス名.変数名] で参照する。
p.age  = 40;

Person.scientificName = "Homo sapiens";
// 静的変数は [クラス名.変数名] で参照する。

また、静的変数・静的メソッドは、数学関数や数学定数などのインスタンスを持つ必要のない関数を定義する場合にも使います。 ( 「関数」 で説明した内容は、 実際には(C# 用語的には)関数ではなく、静的メソッドです。)

using System;

class Math
{
  // sin x を求める関数。
  static double Sin(double x)
  {
    double xx = -x * x;
    double fact = 1;
    double sin = x;
    for(int i=0; i<100; ++i)
    {
      fact *= i; ++i; fact *= i; ++i;
      x *= xx;
      sin += x / fact;
    }
    return sin;
  }
}

class StaticSample
{
  static void Main()
  {
    Console.Write(Math.Sin(1));
  }
}

標準ライブラリの Math.SinConsole.Write などは静的メソッドです。

静的コンストラクタ

静的変数の初期化には、通常のコンストラクタではなく、静的コンストラクタ(static constructor)というものを使います。 静的コンストラクタの定義の仕方は、コンストラクタの前に static キーワードを付ける以外は通常のコンストラクタの定義の仕方と同じです。 例えば、先ほどの Person クラスを例に挙げると以下のようになります。

class Person
{
  string name; // 名前。インスタンス変数。
  int age;     // 年齢。インスタンス変数。

  static string scientificName; // 学名。静的変数。

  // 通常のコンストラクタ
  public Person(string name, int age)
  {
    this.name = name;
    this.age  = age;
  }

  // 静的コンストラクタ
  static Person()
  {
    Person.scientificName = "Homo sapiens";
  }
}

通常のコンストラクタが新しいインスタンスが生成されるたびに呼び出されるのに対して、 静的コンストラクタはプログラムの初めに1度だけ呼び出されます。

サンプル

using System;

// 1台ごとに固有のIDが振られるような何らかの製品。
class Product
{
  static int id_generator;
  int id;

  static Product()
  {
    // 最初に1度だけ呼ばれ、id_generator を 0 に初期化。
    id_generator = 0;
  }

  public Product()
  {
    // 新しい製品が製造されるたびに新しい id を振る。
    id = id_generator;
    id_generator++;
  }

  /// <summary>
  /// その製品のIDを取得する。
  /// </summary>
  public int ID
  {
    get{return id;}
  }
}

class StaticSample
{
  static void Main()
  {
    for(int i=0; i<10; i++)
    {
      Product p = new Product();

      Console.Write("ID: {0}\n", p.ID);
    }
  }
}
ID: 0
ID: 1
ID: 2
ID: 3
ID: 4
ID: 5
ID: 6
ID: 7
ID: 8
ID: 9

静的クラス

Ver. 2.0

標準ライブラリ中の Math クラスのように、 静的なメンバしか持たないクラスがあります。 Math クラスに限らず、 static メンバのみを持ち、インスタンスの作成が不可能なクラスを作りたいことがしばしばあります。

C# 1.0 では、private なコンストラクタを持つ sealed クラスとしてこのようなクラスを作成していました。 このような方法で、「インスタンスが作成不可能」という制約は満たすことが出来ますが、 非 static なメンバを定義することができてしまうという問題がありました。 (決してアクセスすることの出来ない無駄なメンバになってしまいます。)

それに対して、C# 2.0 では、 クラス定義時に static をつけることで、 静的メンバしか定義できないクラスを作ることが出来ます。 このようなクラスを静的クラス(static class)と呼びます。

static class Math
{
  // double x; というような、非 static な変数・メソッドは定義できない。

  // sin x を求める関数。
  static double Sin(double x)
  {
    double xx = -x * x;
    double fact = 1;
    double sin = x;
    for(int i=0; i<100; ++i)
    {
      fact *= i; ++i; fact *= i; ++i;
      x *= xx;
      sin += x / fact;
    }
    return sin;
  }
}

演習問題

問題 1

クラス問題 1Point 構造体に、 2点間の距離を求める static メソッド GetDistance を追加せよ。

/// <summary>
/// A-B 間の距離を求める。
/// </summary>
/// <param name="a">点A</param>
/// <param name="b">点B</param>
/// <returns>距離AB</returns>
public static double GetDistance(Point a, Point b)

また、GetDistance を用いて、 Triangle クラスに三角形の周を求めるメソッド GetPerimeter を追加せよ。

/// <summary>
/// 三角形の周の長さを求める。
/// </summary>
/// <returns>周</returns>
public double GetPerimeter()

解答

Transtation into English

[お問い合わせ](q)