パブリックメンバーとプライベートメンバー
CoddyのGDScriptジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 26/65。
カプセル化とは、オブジェクトがデータとそのデータを変更するメソッドをまとめて保持し、他のコードがどのメンバーを使用できるかを決めることです。他のコード向けのメンバーが、そのオブジェクトのインターフェースを構成します。
GDScriptにはpublicやprivateキーワードはありません。すべてのメンバーに外部からアクセスできます。Godotのスタイルガイドでは、先頭にアンダースコアを付けてprivateなメンバーを示します。
# bank_account.gd
class_name BankAccount
extends RefCounted
var owner_name: String
var _balance: int = 0
var _history: Array[String] = []
func _init(holder: String) -> void:
owner_name = holder
func deposit(amount: int) -> void:
_balance += amount
_record("deposit %d" % amount)
func get_balance() -> int:
return _balance
func _record(entry: String) -> void:
_history.append(entry)owner_name、deposit()、get_balance()は公開されているため、main.gdから使用します。_balance、_history、_record()は非公開です。これらを使用するのはbank_account.gd内のコードだけです。
# main.gd
var account := BankAccount.new("Ada")
account.deposit(50)
account.deposit(20)
print(account.owner_name) # Ada
print(account.get_balance()) # 70アンダースコアは慣例であって、ロックではありません。main.gd内のaccount._balance = 1000000は、エラーなしで実行されます。それでも慣例には従いましょう。_balanceを変更するのがそのクラスだけであれば、残高が間違っている原因はbank_account.gd内のメソッドに限られるため、確認すべきファイルはそれだけです。
GDScriptにもprotectedレベルはありません。サブクラスはプライベートなものも含め、すべてのメンバーを継承するため、BankAccountをextendsするSavingsAccountは、自身のメソッド内で_balanceを使用できます。
_init()や_ready()などのGodotの仮想メソッドも、アンダースコアで始まります。Godotがこれらを呼び出すので、自分のプライベートメソッドに同じ名前を付けないでください。
チャレンジ
簡単hero.gd の Hero クラスを完成させてください。公開メンバーは hero_name、gain_xp()、get_xp()、get_level() です。それ以外は非公開です。
- 非公開変数
_xp(初期値は0)と_level(初期値は1)を追加します。 - 非公開メソッド
_update_level()を追加します。このメソッドは_levelを1 + _xp / 100(整数除算)に設定します。 gain_xp(amount)はamountを_xpに加算し、_update_level()を呼び出します。レベルが上がった場合はtrue、そうでない場合はfalseを返します。get_xp()とget_level()は非公開の値を返します。
提供されているコードは、ヒーローの名前、続いてXPの量がいくつ続くかを読み取り、その後、各行から量を1つずつ読み取ります。各量の処理後、gain_xp() が true を返した場合は Level up! の行を出力し、その後にヒーローの状態を出力します。Ada と量 40、70、250 の場合、次のように出力されます。
Ada: 40 XP, level 1
Level up! Ada is now level 2
Ada: 110 XP, level 2
Level up! Ada is now level 4
Ada: 360 XP, level 4コードは hero.gd に記述してください。main.gd には提供された入出力コードがあり、編集できません。
自分で試してみよう
extends Node
func _ready():
# 用意された入出力コード:そのままにしてください
var hero := Hero.new(OS.read_string_from_stdin())
var count := int(OS.read_string_from_stdin())
for i in count:
var amount := int(OS.read_string_from_stdin())
if hero.gain_xp(amount):
print("Level up! %s is now level %d" % [hero.hero_name, hero.get_level()])
print("%s: %d XP, level %d" % [hero.hero_name, hero.get_xp(), hero.get_level()])
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: GDScriptオンラインコンパイラ