プログラミングパラダイムを浅く理解する

## パラダイムってなんだ？？
パラダイムは物の見方や捉え方。

つまり、どの様に問題を解決していくかの「**方法**」・「**考え方**」的なこととなる

種類として

- 命令型言語
- 宣言型言語
- 構造化プログラミング
- オブジェクト指向言語
- 手続き型言語
- 関数型言語

等がある

## それぞれ特徴とサンプルコードを見てみよう


### **命令型と宣言型**

命令型の反対は宣言型であり、それぞれ「どうやって問題を解決するか(How)」と「何を解決したいか(What)」の違いとなる。

**命令型(どうやって問題を解決するか(How))**

例えば以下のコードのようなもので、どの様に解決するかが明確になっている。

モノに例えると、コーヒーを作るときに豆から作るのに似ていて、豆を挽いて、湯を注いで…みたいな何を作るかだけではなくて、どうやって作るかが明確になっている

車で例えるとMTかな？

```python
numbers = [1, 2, 3, 4, 5]
total = 0

for number in numbers:
    total += number

```

**宣言型(何を解決したいか(What))**

以下のコードのようなもので、どうやるか(How)はあまり重視しておらず、何を解決するか(What)に焦点が当たるような書き方になっている。

先ほどのコーヒーのたとえでいうと、自動販売機にお金を入れてコーヒーを出すみたいな…作る過程はあまり重視しない感じ。

車で例えるとAT的な感じ？

```python
numbers = [1, 2, 3, 4, 5]
total = sum(numbers)
```

### **構造化プログラミング**
現代で使われている書き方はだいたい構造化プログラミングの考えに従って書かれたものなのであまり考えなくてよいが、構造化プログラミングとは「goto」のようなジャンプを無計画に使わないコードのこと。

**非構造化プログラミング風**のコードを無理やりpythonで書いてみると…
```python
age = int(input("年齢を入力してください: "))

if age < 20:
    goto underage
else:
    goto adult
    

underage:
print("お酒は飲めません。")
goto end

adult:
print("お酒を飲むことができます。")

end:

```

みたいな感じ。何をするにしてもgotoが多用されるって感じ。

関数とかも別のコードに飛ぶから非構造化プログラミングなのかと思うかもしれないが、コードをまとめ、わかりやすくするためのものなので構造化プログラミングである。

### オブジェクト指向
データや処理をひとまとめにして管理する考え方。

飲み物A,B,Cを作るとして、オブジェクト指向では、**「飲み物」全体を表す共通の設計図**をまず作る。（例えば容器に入っているとか液体であるとか…）
この設計図を「**クラス**」と呼び、そのクラスを基に、具体的な飲み物（コーヒー、ジュース、紅茶など）の **実体（オブジェクト)**  を作る。

コードで書くと…

```python
# 1. 飲み物の基本的なクラス（共通の特徴や動作を定義する）
class Drink:
    def __init__(self, name, volume, temperature):
        self.name = name             # 飲み物の名前
        self.volume = volume         # 容量（ml）
        self.temperature = temperature  # 温度（Celsius）

    def drink(self, amount):
        if amount > self.volume:
            print(f"{self.name}を飲む量が多すぎます！")
        else:
            self.volume -= amount
            print(f"{self.name}を{amount}ml飲みました。残りは{self.volume}mlです。")

    def describe(self):
        return f"{self.name}: {self.volume}ml, 温度: {self.temperature}度"

# 2. クラスを使って、具体的な飲み物オブジェクトを作成
coffee = Drink("コーヒー", 250, 70)
juice = Drink("ジュース", 300, 5)
tea = Drink("紅茶", 200, 60)

# 3. 飲み物の情報を表示
print(coffee.describe())  # 出力: コーヒー: 250ml, 温度: 70度
print(juice.describe())   # 出力: ジュース: 300ml, 温度: 5度
print(tea.describe())     # 出力: 紅茶: 200ml, 温度: 60度

# 4. 飲み物を飲む
coffee.drink(100)  # 出力: コーヒーを100ml飲みました。残りは150mlです。
juice.drink(350)   # 出力: ジュースを飲む量が多すぎます！
```

メリットとしてはよく言われるけど、以下のようなものがある

- **カプセル化**: それぞれの飲み物が持つ処理やデータは、そのオブジェクト内にまとめられていて管理しやすい。
- **再利用**: 「飲み物」というクラスを一度作れば、様々な飲み物（オブジェクト）を簡単に作成できる。
- **継承:** 設計図を使って抽象的な飲み物を作って新しい設計書を作れる。(例えば 飲み物→コーヒー→ホットコーヒー みたいな)
- **多様性:** 飲み物(オブジェクト)によって同じ関数名でも違う動作をさせられる。例えば drink関数があるとして、普通のドリンクは飲むという動作のみで、ホットドリンクでは冷ましてから飲むみたいな感じで

### 手続き型言語と関数型言語
状態を変化させるか否かの違い。ここでの状態は変数のことが多い。
元の変数の値を変更するか、それとも新しく変数をいれる枠を用意してそこにデータを入れることで計算するかの違い

コードで見てみると

**手続き型(おんなじ財布の使い回し)**

```python
wallet = 1000

wallet += 100 
wallet += 100 
wallet += 100 

print(wallet) # 1300

```

**関数型(いちいち状態が変わるごとに新しい財布を用意している)**

```python
wallet = 1000

wallet1 = wallet + 100
wallet2 = wallet1 + 100
wallet3 = wallet2 + 100

print(wallet1)　# 1100
print(wallet2)　# 1200
print(wallet3)　# 1300

```

こんな感じ

関数型言語は1つの変数に対して値が変わらないのでいつアクセスしても同じ値が入っている保証がある→ 並行処理に優れている

という特性がある