バリデーションロジック
CoddyのLuaジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 47/70。
これまで、データを保護するさまざまな方法を見てきました。命名規則は意図を示し、クロージャは変数を完全に隠し、読み取り専用テーブルはあらゆる変更を防ぎます。しかし多くの場合、その中間が必要です。変更は許可しつつ、有効な変更だけを許可するのです。
ここで setter メソッドが強力なものになります。単に値を代入するだけでなく、setter は新しい値を受け入れる前に、それが妥当かどうかを確認できます。
local Person = {}
Person.__index = Person
function Person:new(name, age)
local obj = {
_name = name,
_age = age
}
setmetatable(obj, Person)
return obj
end
function Person:setAge(newAge)
if newAge < 0 then
print("Error: Age cannot be negative")
return
end
self._age = newAge
end誰かが person:setAge(-5) を呼び出すと、メソッドは無効な入力を検出し、更新を拒否します。オブジェクトの状態は一貫性を保ちます。この保護がなければ、不正なデータによってプログラムが気づかないうちに破損する可能性があります。負の年齢で退職給付を計算することを想像してみてください。
検証は必要に応じて、単純にも複雑にもできます。範囲を確認したり、型を検証したり、値が想定される形式と一致することを確認したりできます。重要な原則は、setter が門番として機能し、妥当なデータだけがオブジェクトに入るようにすることです。
チャレンジ
簡単検証ロジックをセッターメソッドに使用して、health 属性と level 属性を保護する Player class を作成しましょう!これにより、ゲームキャラクターのステータスが不可能な値になることを防げます。
コードを2つのファイルに分けて整理します。
Player.lua: 適切な検証によって player のステータスを管理する class を作成します。コンストラクター:new(name)は、name、_healthを100、_levelを1に設定して player を初期化します。次のメソッドを含めてください。:getName(): player の name を返す:getHealth(): 現在の health を返す:getLevel(): 現在の level を返す:setHealth(value): value が 0 から 100 の間(両端を含む)の場合にのみ health を更新します。無効な場合はError: Health must be between 0 and 100を出力し、value を変更しません。:setLevel(value): value が 1 以上の場合にのみ level を更新します。無効な場合はError: Level must be at least 1を出力し、value を変更しません。
main.lua: Player module を Require し、player の name を読み込んだ後、セッターをテストするための2つの値を読み込みます。player を作成し、最初の値を health に設定しようとし、2番目の値を level に設定しようとした後、player の最終的なステータスを出力します。
3つの入力を受け取ります。
- player の name
- 設定を試みる health の値(有効または無効な数値)
- 設定を試みる level の値(有効または無効な数値)
出力には、無効な設定の試行によるエラーメッセージがあればそれを表示し、その後に player の最終的なステータスを表示します。
Name: {name}
Health: {finalHealth}
Level: {finalLevel}たとえば、入力が Hero、-20、5 の場合、出力は次のようになります。
Error: Health must be between 0 and 100
Name: Hero
Health: 100
Level: 5health setter は -20 を拒否したため(health は 100 のまま)、一方で level setter は 5 を有効な値として受け入れました。
入力が Warrior、75、0 の場合、出力は次のようになります。
Error: Level must be at least 1
Name: Warrior
Health: 75
Level: 1自分で試してみよう
-- Playerモジュールを読み込む
local Player = require('Player')
-- 入力を読み取る
local name = io.read()
local healthValue = tonumber(io.read())
local levelValue = tonumber(io.read())
-- TODO: 指定された名前で新しいプレイヤーを作成する
-- TODO: プレイヤーのhealthをhealthValueに設定することを試みる
-- TODO: プレイヤーのlevelをlevelValueに設定することを試みる
-- TODO: プレイヤーの最終ステータスを次の形式で出力する:
-- Name: {name}
-- Health: {finalHealth}
-- Level: {finalLevel}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Luaオンラインコンパイラ