Menu
Coddy logo textTech

バリデーションロジック

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 が門番として機能し、妥当なデータだけがオブジェクトに入るようにすることです。

challenge icon

チャレンジ

簡単

検証ロジックをセッターメソッドに使用して、health 属性と level 属性を保護する Player class を作成しましょう!これにより、ゲームキャラクターのステータスが不可能な値になることを防げます。

コードを2つのファイルに分けて整理します。

  • Player.lua: 適切な検証によって player のステータスを管理する class を作成します。コンストラクター :new(name) は、name、_health100_level1 に設定して 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つの入力を受け取ります。

  1. player の name
  2. 設定を試みる health の値(有効または無効な数値)
  3. 設定を試みる level の値(有効または無効な数値)

出力には、無効な設定の試行によるエラーメッセージがあればそれを表示し、その後に player の最終的なステータスを表示します。

Name: {name}
Health: {finalHealth}
Level: {finalLevel}

たとえば、入力が Hero-205 の場合、出力は次のようになります。

Error: Health must be between 0 and 100
Name: Hero
Health: 100
Level: 5

health setter は -20 を拒否したため(health は 100 のまま)、一方で level setter は 5 を有効な値として受け入れました。

入力が Warrior750 の場合、出力は次のようになります。

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}
quiz icon腕試し

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

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

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