Menu
Coddy logo textTech

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

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

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

uppercase letterで始まるfieldsexportedです:どのパッケージからもaccessibleです。lowercase letterで始まるfieldsunexportedです:同じパッケージ内でのみaccessibleです:

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

別のパッケージがこの構造体をインポートして使用する場合、アクセスできるのは Exported fields のみです:

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

次の入力が提供されます。

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

たとえば、Alice JohnsonSavings5000.501234が与えられた場合、出力は次のようになります。

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

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

自分で試してみよう

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 は unexported です - ここでは直接アクセスできません
	// それらは構造体の中で安全にカプセル化されています

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

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

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

自分で練習してみよう: Goオンラインコンパイラ