クラスについて深堀するコーナー

Last-modified: Tue, 17 Jan 2023 14:59:17 JST (468d)
Top > クラスについて深堀するコーナー

「オブジェクト」を考えてみる

はじめに

ひつじのアクションで散々無視してきた「class」とか「オブジェクト」についてちゃんと向き合うコーナーです。
厳密ではない情報が含まれます。自信のある人は公式ドキュメントの参照をお勧めします。
https://learn.microsoft.com/ja-jp/dotnet/csharp/programming-guide/

 

オブジェクト指向 is 何?

C#はオブジェクト指向という概念を取り入れたプログラミング言語です。

 

自分の作りたいものをプログラムで再現するとき、どこから考えたら、どこから書いたら良いのかわからないという人は多いかもしれません。
しかし、「オブジェクト」をもとに考えると、作りたいものを簡単にプログラムとしてイメージできるようになると思います。

 

「オブジェクト」とは、データと動作がセットになったもので、オブジェクト指向ではこの「オブジェクト」を基本にしてプログラムを考えます。
例えば、ポケモンのピカチュウは、
"でんきタイプ"や"10レベル"といった「データ」と、"10まんボルトを使う"、"でんこうせっかを使う"などの「動作」
を持ったオブジェクトに当てはめることができそうです。

 

クラス is 何

クラスはよく、オブジェクトの「設計図」にたとえられます。

クラスは「データ」と「アクション」をまとめたデータ構造です。

ポケモンのクラスを作るとすれば、クラスの中にはタイプやレベルなどの「データ」と、技を使う、技を覚えるなどの「アクション」を書けば良いわけです。

 

試しにポケモンクラスを作ってみます。

 

クラスを作るには

  1. class クラスの名前 { クラスの中身 }

のように書きます。

  1. class Pokemon
  2. {
  3.  
  4. }

{}のなかは見やすいように改行してあります。何行改行しても処理に変化はありません。Pokemon のあとの{の位置にも決まりはありません。class クラス名 {の順番で書かれていればどんな形でもクラスと認識されます。
{}のなかにポケモンに必要なものを書いていきます。

 

変数、コメント

まずはポケモンに共通するデータを考えます。
ポケモンの種類で見れば、タイプ、つかえるわざ
個々のポケモンで見ればレベルなどがありそうです。

 

データはクラスの中に「変数」として書きます。変数はデータを保存しておく入れ物みたいなものです。「数」とありますが、中身が数とは限りません。
C#で新しい変数を定義するときは、

  1. 型 変数名;

のようにして書きます。型とは、例えばその変数の中に入るのが文字なのか?数字なのか?ということをあらかじめ決めておくためのものです。
C#では型を決めておかないと変数を定義できません。

  1. class Pokemon
  2. {
  3.     //レベルを作るよ
  4.     int level;
  5. }

ポケモンにレベルを作ってみました。
これを使ってプログラムにメモを残すことができます。
intは整数型なので、変数「level」には整数の値しか入らなくなります。小数を使いたいときはfloatにします
intのまえに半角スペースが4つありますが、見やすいように入れているだけです。何個入れても処理に変化はありません。
処理が終わったら、どこまでが処理かわかるように;で区切ります。これで次の処理と分けることができます。
ポケモンによってレベルは違うので、まだlevelのなかには何も入れていません。

 

タイプも書き入れます。

  1. class Pokemon
  2. {
  3.     //レベルを作るよ
  4.     int level;
  5.     //タイプを作るよ
  6.     string type;
  7. }

stringは文字列型です。文字や文章が入ります。

コラム:セミコロン;のルール

いやちょっと待てclass Pokemon {}は処理じゃないのかと。
C#ではひとつひとつの処理をステートメントと呼び、ステートメントは、セミコロンで終わるか、1 つのブロック{}で構成されます。
{}のあとには;は要らないことが多いですが、例外もあります。
(かなり語弊があるので正確な情報は↓で確認してください。)
https://learn.microsoft.com/ja-jp/dotnet/csharp/programming-guide/statements-expressions-operators/statements
よくわからなければ、とりあえず;をつけておけば大丈夫です。;;;;;;;と;をたくさん書いてもエラーにはなりません。

 

配列

ここで先に技のクラスを作ってしまいます。
技に共通するデータを考えると
技の名前、タイプ、ダメージなどがありそうです。

  1. class Pokemon
  2. {
  3.     //レベルを作るよ
  4.     int level;
  5.     //タイプを作るよ
  6.     string type;
  7. }
  8.  
  9. class Skill
  10. {
  11.     //技名
  12.     string name;
  13.     //技のタイプ
  14.     string type;
  15.     //威力
  16.     int damage;
  17. }

Pokemonクラスの下に新しくSkill(技)クラスが作られました。
作った技をポケモンが持てるようにPokemonクラスを改良します。

  1. class Pokemon
  2. {
  3.     //レベルを作るよ
  4.     int level;
  5.     //タイプを作るよ
  6.     string type;
  7.     //技を持つよ Skillは型名, skillが変数名
  8.     Skill skill;
  9. }

自分の作ったクラスもこのように型として使うことができます。
ところで、ポケモンは複数の技を持っています。
技ごとに変数を作っても良いですが、同じ型の変数がいくつも欲しいときは配列が便利です。
配列は

  1. 型名[] 変数名;

のように書きます。

  1. class Pokemon
  2. {
  3.     //レベルを作るよ
  4.     int level;
  5.     //タイプを作るよ
  6.     string type;
  7.     //複数の技を持つよ
  8.     Skill[] skill;
  9. }

このようにすると、skillにはSkill型のものをSkill, Skill, ...のように並べて入れることができるようになります。

 

メソッド

クラスの持つアクションのことを「メソッド」と呼びます。クラスの持つデータ(変数)のことは「フィールド」と呼びます。
メソッドには、処理を行うだけのものと、処理の結果(戻り値)を返すものがあります。
Pokemonクラスに、技を使うメソッドを持たせてみます。
処理を行うだけのメソッドは

  1. void メソッド名()
  2. {
  3.     //処理内容
  4. }

のように書きます。

  1. class Pokemon
  2. {
  3.     //レベルを作るよ
  4.     int level;
  5.     //タイプを作るよ
  6.     string type;
  7.     //複数の技を持つよ
  8.     Skill[] skill;
  9.     //技を使うよ
  10.     void useSkill()
  11.     {
  12.         //あとで処理を書くよ
  13.     }
  14. }
 

クラスの継承

ポケモンにはピカチューとかライチューとかいろいろな種類がいると思います。
先ほどPokemonクラスで全ポケモンに共通するデータやアクションをまとめたので、今度はそれを使ってポケモンを種族ごとに作っていきます。
クラスは「継承」によってデータやアクションを他のクラスに引継ぐことができます。
クラスの継承は

  1. class 作るクラス名 : 継承するクラス名 {}

のように書きます。
Pokemonクラスを継承したPikachuクラスを作ります。

  1. //上にさっきまでのコード
  2.  
  3. class Pikachu : Pokemon
  4. {
  5. }