2012-06-06 3 views
0

Итак, я пытаюсь написать простой класс в Lua для представления CSV поля:попытка вызвать метод «печать» (нилъ значение), когда ООП реализации в Lua

csv_entry = {} 
csv_entry.__index = csv_entry 

function csv_entry.create(...) 
    return arg 
end 

function csv_entry:tostring() 
    local str = string.char() 
    for i,v in ipairs(self) do 
     if i < #self then 
    str = str .. v 
     else 
    str = str .. v .. ", " 
     end 
    end 
end 

function csv_entry:print() 
    print(self:tostring()) 
end 

Но когда я пытаюсь использовать этот класс, как это:

c = csv_entry.create("Volvo", 10000, "Eric") 
c:print() -- line 25 

Я получаю сообщение об ошибке

lua: csv.lua:25: attempt to call method 'print' (a nil value) 

И я не могу понять этот вопрос здесь. Что я делаю не так?

+4

Ваша функция 'create' похоже, ничего не делает. Он возвращает 'arg', что равно нулю. Или есть что-то еще, что вы не показываете? –

ответ

3

Вы, вероятно, имел в виду, чтобы сделать это:

function csv_entry.create(...) 
    return setmetatable(arg, csv_entry) 
end 

Опубликованная версия cvs_entry.create просто возвращает его аргументы, упакованные в таблицу, так что этот код:

c = csv_entry.create("Volvo", 10000, "Eric") 
c:print() 

точности эквивалентно к этому коду:

c = {"Volvo", 10000, "Eric"} 
c:print() 

c не содержит записи print, поэтому c.print возвращает nil и c:print() сбой, потому что вы пытаетесь «позвонить» nil.


Side Примечание: неявные arg параметров переменных числа функций были удалены в Lua 5.1 (6 лет назад). Правильный способ сделать это сейчас:

function csv_entry.create(...) 
    local arg = {...} 
    return setmetatable(arg, csv_entry) 
end 

Или просто:

function csv_entry.create(...) 
    return setmetatable({...}, csv_entry) 
end 

Пока мы здесь: вы собираетесь получить не выход из csv_entry:tostring, потому что это Безразлично Я ничего не верну. Кроме того, если все, что вы пытаетесь сделать, это объединить кучу элементов с запятой разделителей, вы можете использовать table.concat:

function csv_entry:tostring() 
    return table.concat(self, ', ') 
end 
0

я переписать код, чтобы встретить то, что для, она работает хорошо для меня:

csv_entry = {} 

function csv_entry:create(...) 
    o = {content = {}} 
    self.__index = self; 
    setmetatable(o, self) 
     for i = 1, arg.n do 
      o.content[i] = arg[i]; 
     end 
    return o; 
end 

function csv_entry:tostring() 
    local resStr = "" 
    for i, v in pairs(self.content) do 
     resStr = resStr .. v; 
     if i < #(self.content) then 
      resStr = resStr .. ", " 
     end 
    end 
    return resStr; 
end 

function csv_entry:print() 
    print(self:tostring()) 
end 

c = csv_entry:create("Volvo", 10000, "Eric") 
c:print() 

как @Mud слова, создать (...) в коде просто обычный вызов и возвращает все аргументы ..., если вы хотите csv_entry работает как класс, то вы должны поставить коды, которые устанавливают metatable и __index в create (...), и возвращают экземпляр из класса csv_entry

Смежные вопросы