なぜstaticをつけるとnewが要らなくなるのか?税込み価格計算で理解するstatic入門

広告

はじめに

前回までの「Studentクラス」チュートリアルでは、new Student()を使ってインスタンスを作り、student1.ShowScore()のようにインスタンス経由でメソッドを呼び出しました。

では、クラスの中の処理は、いつもnewしてから呼び出さないといけないのでしょうか?

今回は、税込み価格を計算するプログラムを題材に、staticをつけると何が変わるのか、そしてなぜインスタンスを作る必要がなくなるのかを、入力しながら確認していきます。

今回作るプログラム

1000円の商品を例に、税込み価格を表示するプログラムを作ります。実行結果は次のとおりです。

1000円の税込み価格は1100円です。

税率は10%として計算します。この例では説明を簡単にするため、整数計算で小数点以下を切り捨てます。実際の料金計算では、decimalと決められた端数処理のルールを使用します。

Visual Studioで新しいプロジェクトを作る

  1. 「新しいプロジェクトの作成」をクリックする
  2. 「コンソール アプリ」を選ぶ
  3. 言語がC#になっていることを確認する
  4. ソリューション名とプロジェクト名に「TaxCalculatorTutorial」と入力する
  5. 「作成」をクリックする

入力順1:まずは普通に計算する

最初はクラスを使わず、Program.csの中で直接計算します。

using System;

namespace TaxCalculatorTutorial
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int price = 1000;
            int total = price * 110 / 100;

            Console.WriteLine($"{price}円の税込み価格は{total}円です。");
        }
    }
}

ここでは、まず普通に計算できることを確認します。

入力順2:Calculatorクラスを作る

税込み価格を計算する処理を、Calculatorクラスの中に移します。Studentクラスのときと同じように、まずはインスタンスメソッドとして書きます。

using System;

namespace TaxCalculatorTutorial
{
    internal class Program
    {
        static void Main(string[] args)
        {
        }
    }

    class Calculator
    {
        public int CalculateTotal(int price)
        {
            return price * 110 / 100;
        }
    }
}

CalculateTotalは、金額を受け取って税込み価格を返すメソッドです。

入力順3:new Calculator()を書いて呼び出す

Studentクラスのときと同じように、newを使ってインスタンスを作ってから呼び出します。

using System;

namespace TaxCalculatorTutorial
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Calculator calculator = new Calculator();
            int total = calculator.CalculateTotal(1000);

            Console.WriteLine($"1000円の税込み価格は{total}円です。");
        }
    }

    class Calculator
    {
        public int CalculateTotal(int price)
        {
            return price * 110 / 100;
        }
    }
}

これで動きますが、ここで少し立ち止まって考えてみます。Studentのときは、student1student2で名前や点数が違いました。だから、それぞれ別のインスタンスとしてNameScoreというデータを持たせる意味がありました。

では、このcalculatorはどうでしょうか。calculator.Nameのような、生徒ごとに違うデータを持っているわけではありません。ただ計算するだけの箱として、インスタンスを作っています。

Calculatorクラスから作られたインスタンスが、保持データを持たないことを示す図
Calculatorのインスタンスは、Studentと違ってデータを持たない空の実体です。

Calculatorという設計図からnewで実体を作ってはいますが、その実体は空っぽです。中に何も保存していません。計算に使うのは、そのつど渡されたpriceだけです。

入力順4:staticを付けてみる

CalculateTotalstaticを付けてみます。

using System;

namespace TaxCalculatorTutorial
{
    internal class Program
    {
        static void Main(string[] args)
        {
            int total = Calculator.CalculateTotal(1000);

            Console.WriteLine($"1000円の税込み価格は{total}円です。");
        }
    }

    static class Calculator
    {
        public static int CalculateTotal(int price)
        {
            return price * 110 / 100;
        }
    }
}

new Calculator()がなくなり、Calculator.CalculateTotal(1000)のように、クラス名から直接呼び出せるようになりました。

staticメソッドを型名から直接呼び出すことを示す図
staticなら、インスタンスを経由せず、型名から直接メソッドを呼び出せます。

インスタンスを経由せず、型名であるCalculatorから直接メソッドを呼び出しています。

なぜstaticが便利なのか

ここのポイントです。StudentクラスとCalculatorクラスを比べてみます。

Studentはインスタンスごとのデータを持ち、Calculatorはこの例では状態を持たないためstaticにできることを比較する図
Studentはインスタンスごとの状態を持つためインスタンスが必要ですが、今回のCalculatorは状態を持たないためstaticメソッドにできます。

staticメソッドは、特定のインスタンスに属さないメソッドです。そのため、インスタンスのフィールドやプロパティを直接使うことはできません。今回のCalculatorはインスタンスごとの状態を持たないため、インスタンスを作らずに利用できます。この例では、使うたびにnew Calculator()と書く必要はありません。

Math.Max(a, b)Console.WriteLine(...)のように、普段newせずに使っているメソッドも、同じ理由でstaticとして作られています。

今回のまとめ

  • staticを付けると、newせずにクラス名から直接メソッドを呼び出せる
  • StudentはNameやScoreという、インスタンスごとに違うデータを持つのでインスタンス化が必要
  • Calculatorはインスタンスごとの状態を持たないので、この例ではインスタンス化しなくてもよい
  • インスタンスごとの状態を必要としない処理は、staticメソッドにできる

Math.MaxConsole.WriteLineのように、C#にはすでにたくさんのstaticメソッドが用意されています。次に見かけたときは、「これは特定のインスタンスに属さない処理なんだな」という視点で眺めてみてください。

訪問数 8 回, 今日の訪問数 8回

広告

C#

Posted by hidepon