Почему это работает с оператором точки? - PullRequest
0 голосов
/ 25 декабря 2018

В настоящее время я изучаю классы http://howtomakeanrpg.com/a/classes-in-lua.html и пытаюсь найти логику использования оператора двоеточия.Из того, что я понимаю, единственное, что оператор двоеточия делает вне определения функции, - это передает таблицу, которая находится перед ним, как невидимый параметр.

Ниже я создал по-разному трех монстров, чтобы попытаться понять логику этого.Я вообще не понимаю этого, потому что при вызове второго монстра я не нуждаюсь в том, чтобы передать монстра в таблицу ???И почему я могу указать в качестве параметра таблицу monster_3 (которую я тестировал как таблицу типов), разве не таблица: Monster передаваемая таблица?Или это просто точка, которая говорит, что Create находится внутри таблицы Monster.Это просто не имеет никакого смысла для меня вообще.

Я также думал, что новый объект добавлен в родительскую таблицу, но когда я проверяю, находится ли monster_ (число) внутри таблицы: Monster, я получаю ноль.Какие???Тогда где хранятся эти новые таблицы monster_1,2,3 ???

Спасибо за просмотр,

Xpali

   Monster = {}
function Monster:Create()
    local this =
    {
        name = "orc",
        health = 10,
        attack = 3
    }

    function this:WarCry()
        print(self.name .. ": GRAAAHH!!!")
    end

    return this

end

monster_1 = Monster:Create()
monster_2 = Monster.Create()
monster_3 = Monster.Create(monster_3)

print(monster_1.name) -- orc
print(type(monster_1)) -- table
print(type(Monster.monster_1)) -- nil

print(monster_2.name) -- orc
print(type(monster_2)) -- table
print(type(Monster.monster_2)) -- nil

print(monster_3.name) -- orc
print(type(monster_3)) -- table 
print(type(Monster.monster_3)) -- nil

monster_1:WarCry() -- orc: GRAAAHH!!!
monster_2:WarCry() -- orc: GRAAAHH!!!
    monster_3.WarCry(monster_3) -- orc: GRAAAHH!!!    

1 Ответ

0 голосов
/ 25 декабря 2018

Приведенный выше код не очень выразителен для создания экземпляров классов, поскольку используемый конструктор не имеет аргументов.В результате все 3 экземпляра идентичны.Кроме того, «Monster.monster_1» и аналогичные НЕ являются экземплярами, они являются nils.

Чтобы увидеть что-то более интересное, я подготовил следующий пример кода:

-- Default properties values
local Monster = {
  name = "orc",
  health = 10,
  attack = 3
}

-- constructor
function Monster:Create(instance_name)
  -- take defaults from self (that is Monster table)
  instance_name = instance_name or self.name
  return {
    name = instance_name,
    health = self.health,
    attack = self.attack,
    WarCry = function(this)
      print(this.name .. ": GRAAAHH!!!")
    end
  }
end

monster_1 = Monster:Create()
monster_2 = Monster:Create("named") 
--monster_2 = Monster.Create() -- Incorrect use!
--monster_3 = Monster.Create(monster_3) -- Incorrect use!

print(monster_1.name) -- orc
print(type(monster_1)) -- table

print(monster_2.name) -- named
print(type(monster_2)) -- table

monster_1:WarCry() -- orc: GRAAAHH!!!
monster_2:WarCry() -- named: GRAAAHH!!!

Теперь конструктор имеетявный аргумент («имя_экземпляра») и неявный (таблица монстров).Последнее необходимо для использования ключевого слова "self".Поэтому мы не должны использовать точечный синтаксис при создании экземпляров, это приведет к ошибке.Если мы избегаем «self» в определении конструктора, мы можем использовать точечный синтаксис без ошибок, как вы можете видеть ниже:

-- constructor
function Monster:Create(instance_name)
  -- take defaults from self (that is Monster table)
  instance_name = instance_name or Monster.name
  return {
    name = instance_name,
    health = Monster.health,
    attack = Monster.attack,
    WarCry = function(this)
      print(this.name .. ": GRAAAHH!!!")
    end
  }
end

monster_1 = Monster:Create()
monster_2 = Monster.Create(nil, "named") 

Обратите внимание на «nil» в последнем вызове.Этот аргумент обязателен, потому что конструктор был определен синтаксисом двоеточия, но мы используем точечный вызов.Если мы опускаем аргумент "nil", значение "named" будет рассматриваться как родительская таблица в контексте двоеточия.

ADDED:

Мы также можем создать конструктор, используя синтаксис точки:

Monster.CreateByDot = function(instance_name)
  instance_name = instance_name or 'Noname';
  return {
    name = instance_name,
    WarCry = function(this) 
      print(this.name .. ": GRAAAHH!!!")
    end
  } 
end

monster_3 = Monster.CreateByDot()
monster_4 = Monster.CreateByDot('Fourth')

monster_3:WarCry() -- Noname: GRAAAHH!!!
monster_4:WarCry() -- Fourth: GRAAAHH!!!

и посмотрите аргумент "имя_экземпляра" в действии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...