Menu
Coddy logo textTech

公開フィールドと非公開フィールド

CoddyのGOジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 47/107。

Goでは、構造体レベルでのカプセル化は、フィールド名の大文字・小文字によって制御されます。この単純なルールによって、構造体が定義されているパッケージの外からフィールドにアクセスできるかどうかが決まります。

大文字で始まるフィールドはエクスポートされ、どのパッケージからでもアクセス可能です。小文字で始まるフィールドはエクスポートされず、同じパッケージ内からのみアクセス可能です:

// パッケージ "user" 内
type User struct {
    Name     string  // 公開 - どこからでもアクセス可能
    Email    string  // 公開 - どこからでもアクセス可能
    password string  // 非公開 - "user" パッケージ内でのみアクセス可能
    age      int     // 非公開 - "user" パッケージ内でのみアクセス可能
}

別のパッケージがこの構造体をインポートして使用する場合、エクスポートされたフィールドとしかやり取りできません。

// パッケージ "main" 内
import "user"

func main() {
    u := user.User{
        Name:  "Alice",      // 動作します
        Email: "a@mail.com", // 動作します
        // password: "secret", // コンパイルエラー: 未知のフィールドです
    }
    
    fmt.Println(u.Name)     // 動作します
    // fmt.Println(u.password) // コンパイルエラー: エクスポートされていないフィールドは参照できません
}

このメカニズムは、機密データや内部の実装の詳細を保護します。passwordフィールドはパッケージの外部から直接読み取ったり変更したりすることはできず、他のコードは提供されたメソッドを使用することを強制されます。これは、オブジェクト指向プログラミングにおけるカプセル化の核心的な原則である「データ隠蔽」を実現するためのGoのアプローチです。

challenge icon

チャレンジ

簡単

エクスポートされたフィールドとエクスポートされていないフィールドを通じてカプセル化を実証する銀行口座システムを構築しましょう。機密性の高い財務データを保護しながら、安全な公開情報を公開するパッケージを作成します。

コードを2つのファイルに分けて構成します:

  • account.go: 適切なデータ保護を備えた実際の銀行口座をモデル化した BankAccount 構造体を main パッケージに作成します:
    • HolderName (エクスポートあり) - 口座名義人の名前。公開しても安全です。
    • AccountType (エクスポートあり) - 口座の種類(例: "Savings", "Checking")
    • balance (エクスポートなし) - 実際の残高。保護される必要があります。
    • pin (エクスポートなし) - 口座のPIN。非常に機密性の高いデータです。
    名義人名、口座タイプ、初期残高、およびPINを受け取り、新しい BankAccount へのポインタを返すコンストラクタ関数 NewBankAccount を追加します。また、Account: [HolderName] ([AccountType]) という形式を返すメソッド GetPublicInfo() string を追加します。
  • main.go: 入力から口座の詳細を読み取り、コンストラクタを使用して BankAccount を作成し、カプセル化を実証します。メソッドを使用して公開情報を出力し、次に各エクスポートされたフィールドに直接アクセスして別々の行に出力します。エクスポートされていないフィールド(balancepin)は保護されており、コンストラクタを通じてのみ設定できます。

以下の入力が提供されます:

  • 1行目: 口座名義人の名前
  • 2行目: 口座の種類
  • 3行目: 初期残高(浮動小数点数として)
  • 4行目: PINコード

例えば、Alice Johnson, Savings, 5000.50, 1234 が与えられた場合、出力は以下のようになります:

Account: Alice Johnson (Savings)
Holder: Alice Johnson
Type: Savings

残高とPINが出力に表示されないことに注目してください。これらは構造体の中に安全に隠されており、パッケージ内からのみアクセス可能です。これがカプセル化の仕組みです。機密データは保護され、公開情報はアクセス可能なまま維持されます。

チートシート

Goでは、カプセル化は構造体のフィールド名の先頭文字が大文字か小文字かによって制御されます:

  • 大文字で始まるフィールドはエクスポートされます(どのパッケージからでもアクセス可能です)
  • 小文字で始まるフィールドはエクスポートされません(同じパッケージ内からのみアクセス可能です)
type User struct {
    Name     string  // エクスポートされる - どこからでもアクセス可能
    Email    string  // エクスポートされる - どこからでもアクセス可能
    password string  // エクスポートされない - 同じパッケージ内からのみアクセス可能
    age      int     // エクスポートされない - 同じパッケージ内からのみアクセス可能
}

別のパッケージの構造体を使用する場合、エクスポートされたフィールドのみがアクセス可能です:

import "user"

func main() {
    u := user.User{
        Name:  "Alice",      // 動作する
        Email: "a@mail.com", // 動作する
        // password: "secret", // コンパイルエラー: 未知のフィールド
    }
    
    fmt.Println(u.Name)     // 動作する
    // fmt.Println(u.password) // コンパイルエラー: エクスポートされていないフィールドは参照できません
}

この仕組みは、機密データや内部の実装詳細を保護し、外部のコードがアクセスするために提供されたメソッドを使用するように強制します。

自分で試してみよう

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// 口座名義人を読み込む
	holderName, _ := reader.ReadString('\n')
	holderName = strings.TrimSpace(holderName)

	// 口座種別を読み込む
	accountType, _ := reader.ReadString('\n')
	accountType = strings.TrimSpace(accountType)

	// 初期残高を読み込む
	balanceStr, _ := reader.ReadString('\n')
	balanceStr = strings.TrimSpace(balanceStr)
	balance, _ := strconv.ParseFloat(balanceStr, 64)

	// PINを読み込む
	pinStr, _ := reader.ReadString('\n')
	pin := strings.TrimSpace(pinStr)

	// TODO: コンストラクタを使用して新しい BankAccount を作成する
	// account := NewBankAccount(...)

	// TODO: GetPublicInfo() メソッドを使用して公開情報を出力する

	// TODO: エクスポートされたフィールドに直接アクセスして名義人名を出力する
	// fmt.Println("Holder:", ...)

	// TODO: エクスポートされたフィールドに直接アクセスして口座種別を出力する
	// fmt.Println("Type:", ...)

	// Note: balance と pin はエクスポートされていません。ここでは直接アクセスできません
	// これらは構造体内に安全にカプセル化されています

	_ = balance // balance を使用する際は、この行を削除してください
	_ = pin     // pin を使用する際は、この行を削除してください
}
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン