25行でC#のオブジェクト指向がわかった気になる

# 25行でC#のオブジェクト指向がわかった気になる

> この物語はいつもLinuxでC書いてるプログラマが急にC#の案件を振られ、勉強のためいろいろコードを書いていたら、なんとなくオブジェクト指向がわかった気になる過程を淡々と描くものです。間違ってるかもしれないので過度な期待はしないでください。

## 前提知識

端々にCとの比較が出てきますが、Cの入門書をちょっとでもかじっていれば問題ないと思います。

## 注意！！

**これはあくまでも自分がオブジェクト指向という考え方を勉強し、納得する過程をなぞったものであり、厳密な定義とは異なる解釈をしている場合があります。**

## まずは簡単な文法を確認

> オブジェクト指向言語触るの初めて(´・ω・｀)

### クラス

```csharp
class クラス名 {
  static void Main() {
    // 処理とかいろいろ
  }
}
```

ふむふむ。なんとなくJavaとかC++でclassなんとかって書いてあるの見た気がする。

### 名前空間

```csharp
namespace HelloWorld {
  class Program {
    // 処理とかいろいろ
  }
}
```

`namespace`？まあ、キーワード名からして`#ifndef __MYLIB_H__`って書かなくても変数名とか関数名が衝突しないようにするためのものかな。

### hello worldでも書いてみるか

```csharp:hello1.cs
using System;

namespace HelloWorld {
  class Program {
    static void Main() {
      Console.WriteLine("Hello World");
    }
  }
}
```

コンパイルして実行。別にVisual Studioからでもいいけど、Vim大好きだから。**Vim大好きだから！**

```
C:\CSharp> csc hello1.cs
Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
Copyright (C) Microsoft Corporation. All rights reserved.

C:\CSharp> hello1.exe
Hello World

C:\>
```

おーけーおーけー

### 変数作ってみる

```csharp:hello2.cs
using System;

namespace HelloWorld {
  class Program {
    static void Main() {
      int i;
      int[] a = new int[5];

      for (i = 0; i < a.Length; i++) {
        a[i] = i * 100;
        Console.WriteLine("a[{0}] = {1}", i, a[i]);
      }
    }
  }
}
```

変数作って、配列作って、`for`で`a[]`の全要素にアクセスしてる。`a.Length`はオブジェクト指向っぽい書き方だな。

ん？

`int i;`はCと同じ書き方なのに`new int[5]`ってなんだ？

### `int i`と`new int[5]`の違い

Microsoftのドキュメントを開く。[→ 共通型システム](https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/types/#the-common-type-system)
C#の型は**値型**と**参照型**に大きく分けられる、と。

> 参照型？難しそうな言葉出てきた Oo(´・ω・｀)

要は、値型は数字の型と`struct`で定義されたもので、参照型は`class`で定義されたもの、と。`struct`で定義される構造体はCでも勝手にメモリーが割り当てられる。`class`は自分でメモリーを`new`で割り当てる必要がある。`malloc()`のC#版が`new`か。しかもガーベッジコレクションが勝手に不要になったメモリー回収するから`free()`不要。（Cも構造体の中にポインターがあってmallocするとかは一旦忘れて）

つまりあれか、**参照型はCのポインターみたいなもんか！**

> 色んな人に怒られそうなザックリ理解(´∀｀；)

#### 注意！！
厳密には違います。`int`型は`System.Int32`のエイリアス（別名）でしかなく、`string`も`System.String`のエイリアスです。C#では源泉を辿っていくとすべてのクラスは`System.Object`の派生になっています。正確には値型は`System.ValueType`を継承するクラス、参照型はそれ以外に`System.Object`クラスから脈々と派生してできたクラス。

### クラスを作ってみる

```csharp:hello3.cs
using System;

namespace HelloWorld {
  class SuperText {
    public string AddWorld(string s) {
      return s + " World";
    }
  }

  class Program {
    static void Main() {
      string s;
      SuperText t = new SuperText();

      s = Console.ReadLine();
      s = t.AddWorld(s);

      Console.WriteLine(s);
    }
  }
}
```

`SuperText t = new SuperText();`はさっき調べたように、クラスだからnewでインスタンスを作る。`Console.ReadLine()`はCの`scanf()`みたいなやつ。`Console.WriteLine()`は`printf()`みたいなやつ。

`s = t.AddWorld();`は`SuperText`クラスの`AddWorld()`を呼び出してるんだな？見に行くぞ。

`public string AddWorld(string s) {`は文字列型の引数を取って、外部からアクセスできるように`public`になってる関数（C#ではメソッドと言う）だな。`private`と書くと他のクラスから使えなくなる。Cではファイル単位でやっていたアクセス制限をC#ではクラスと言う単位でやってる。

あれ？

オブジェクト指向って確か、データとそれを操作するメソッドを合わせたものじゃなかったっけ？`string s`がボッチになっとる。

### オブジェクト指向になる

つまり、`SuperText`クラスに`string s`と`AddWorld()`の両方を入れればいい。

```csharp:hello4.cs
using System;

namespace HelloWorld {
  class SuperText {
    private string str;

    public void AddWorld(string s) {
      str = s + " World";
    }

    public string GetResult() {
      return str;
    }
  }

  class Program {
    static void Main() {
      SuperText t = new SuperText();

      t.AddWorld(Console.ReadLine());

      Console.WriteLine(t.GetResult());
    }
  }
}
```

今度は`SuperText`クラスの中にデータを保存する`string str`とそれを操作する`AddWorld()`メソッドと`GetResult()`メソッドがある。これで、文字列`str`にはprivate修飾子がついているので、他のクラスが逆立ちしても直接`str`の値を操作することができない。これがカプセル化（または隠蔽）というやつか。Cでもグローバル変数を使わず、きっちりとファイルスコープで変数とそれをイジれる関数を管理すればいいんだけどね。メンドイよね。クラスを使うとそれがサクッと出来ちゃう。

**これがオブジェクト指向なのか。納得。(\*ﾟ∀ﾟ)**

C#には他にもインターフェイスやタプルやラムダ式やジェネリックやいろいろな概念が出てきます。一見して難解な概念でもそれはただ学習者を苦しめるためのものではなく、何かしら**プログラミングを楽にする**ためもの。

言語の勉強で行き詰まってしまったら「**この概念があるとどんないいことがあるのかな**」と考えてみましょう。

> で、どこが25行なのかというと、最後のソース`hello4.cs`です。