Apexのアクセス修飾子

SalesforceのApexでは、アクセス修飾子（**global、public、protected、private**）を使って、クラスやメソッド、変数のアクセス範囲を制御できます。  
各修飾子の意味と、実際の使われ方を具体例とともに整理。  

---

## **1. global（グローバル）**
### **概要**
- **Apexの中で最も広いアクセス範囲**。
- **Managed Packageを作成した場合、パッケージの外部（別のSalesforce組織）からもアクセスできる**。
- 通常のApexコードではほとんど使わず、**Managed Package（マネージドパッケージ）を提供するとき** に使用。

### **使用例**
```apex
global class MyGlobalClass {
    global static void showMessage() {
        System.debug('This is a global method.');
    }
}
```
### **実際の使われ方**
✅ **Managed PackageでAPIを公開** する場合に使用。  
✅ **組織内のコードだけで使う場合は不要（publicで十分）**。  

**⚠️ 注意**  
- **一度globalにすると、削除・変更ができない**（パッケージのバージョン管理上の制約）。  
- **publicで十分な場合はglobalを避ける**（不要な公開を防ぐ）。  

---

## **2. public（パブリック）**
### **概要**
- **同じ名前空間（通常は同じSalesforce組織）内でアクセス可能**。
- **Managed Package内では外部から見えない**（パッケージ内でのみ使用可）。
- **標準的なクラスの定義に使う**。

### **使用例**
```apex
public class MyPublicClass {
    public void sayHello() {
        System.debug('Hello from public class!');
    }
}
```

### **実際の使われ方**
✅ **Salesforce組織内の他のクラスやトリガーから使う一般的なクラス**。  
✅ **HelperクラスやServiceクラス** に使う。  

**⚠️ 注意**  
- **publicは組織内であればどこからでもアクセス可能なので、むやみに公開しない**。  
- **内部でしか使わないならprivateやprotectedを考慮**。  

---

## **3. private（プライベート）**
### **概要**
- **定義されたクラス内でのみアクセス可能**（クラスの外からはアクセス不可）。
- **カプセル化（データの隠蔽）を強化** するために使用。

### **使用例**
```apex
public class MyClass {
    private Integer counter = 0; // クラス内だけで使う変数
    
    public void increment() {
        counter++;
        logCounter(); // privateメソッドはクラス内でのみ使用可
    }
    
    private void logCounter() {
        System.debug('Counter: ' + counter);
    }
}
```

### **実際の使われ方**
✅ **外部から変更されたくないデータを隠蔽する**（例えば、カウンターや一時データ）。  
✅ **内部処理のメソッドを外部に公開しない**（logCounterメソッドのような補助的処理）。  

**⚠️ 注意**  
- **privateを使いすぎるとテストしづらくなる**（テストメソッドから直接アクセスできない）。  
- **@TestVisible アノテーションを使うと、テスト時にprivateメンバーをアクセス可能にできる**。  

```apex
public class MyClass {
    @TestVisible private Integer counter = 0;
}
```

---

## **4. protected（プロテクテッド）**
### **概要**
- **同じクラス内、またはそのクラスを継承したクラス（子クラス）からアクセス可能**。
- **別のクラスからはアクセス不可**（例：別のHelperクラスからはアクセスできない）。
- **サブクラスでのみ使えるようにしたいデータやメソッドに適用**。

### **使用例**
```apex
public class ParentClass {
    protected String message = 'Hello from Parent';
    
    protected void showMessage() {
        System.debug(message);
    }
}

public class ChildClass extends ParentClass {
    public void display() {
        showMessage(); // 継承関係にあるのでアクセス可能
    }
}
```

### **実際の使われ方**
✅ **拡張可能な基底クラス（親クラス）で、子クラス専用のメソッドを用意する**。  
✅ **完全に隠したいわけではないが、外部には公開したくないデータを扱う**。  

**⚠️ 注意**  
- **Apexでは、protectedは「同じ名前空間内のクラス」からでもアクセスできない（継承関係にあるクラスだけ）**。  
- **別のクラスで使うならpublicやprivateを適切に選ぶ**。  

---

## **5. 各修飾子の比較まとめ**
| 修飾子 | アクセス可能な範囲 | 使いどころ | 注意点 |
|--------|------------------|------------|--------|
| **global** | 全組織（Managed Package外からも可） | Managed Packageの公開API | 一度公開すると変更不可 |
| **public** | 同じ組織内の全クラス | ユーティリティクラス、Serviceクラス | できるだけ不要な公開を避ける |
| **protected** | 同じクラス+継承クラス | 継承前提の設計 | 同じ組織内の別クラスからはアクセス不可 |
| **private** | クラス内のみ | 内部処理や隠蔽したいデータ | テストしづらい（@TestVisibleを活用） |

---

## **6. どの修飾子を使うべき？**
✅ **基本は `private` で隠し、必要になったら `public` にする**（**最小限の公開を原則にする**）。  
✅ **継承を考えるなら `protected` を使う**（**拡張性を考慮**）。  
✅ **組織内の共通処理は `public` でOK**（**ただし、不要な公開は避ける**）。  
✅ **Managed Packageを作るときのみ `global` を使う**（**外部に公開するもの限定**）。  

---

## **7. 実際のプロジェクトでの使われ方**
**❌ 悪い例（何でもpublic）**
```apex
public class BadExample {
    public Integer counter = 0;
    
    public void increment() {
        counter++;
    }
}
```
→ **外部からcounterを直接変更できるので、意図しないバグの元になる**。  

**✅ 良い例（カプセル化）**
```apex
public class GoodExample {
    private Integer counter = 0; // 外部から変更できないようにする
    
    public void increment() {
        counter++;
    }
    
    public Integer getCounter() {
        return counter;
    }
}
```
→ **外部から直接counterを変更できないので、安全性が高い**。  

---

## **8. まとめ**
- **`private` を基本にし、必要に応じて `protected` や `public` を使う**。  
- **`global` はManaged Package向け、通常は不要**。  
- **適切なアクセス制御をすることで、安全で拡張しやすいApexコードになる**！