• lua 元表和面向对象


    lua元表的应用也非常广泛,小到运算符重载,大到面向对象实现,一下列举了一些运算符的重载和类继承的例子:

    一:运算符重载:当想将两个对象相加怎么办?

    • __addthe addition (+) operation. If any operand for an addition is not a number, Lua will try to call a metamethod. It starts by checking the first operand (even if it is a number); if that operand does not define a metamethod for __add, then Lua will check the second operand. If Lua can find a metamethod, it calls the metamethod with the two operands as arguments, and the result of the call (adjusted to one value) is the result of the operation. Otherwise, if no metamethod is found, Lua raises an error.
    • __subthe subtraction (-) operation. Behavior similar to the addition operation.
    • __multhe multiplication (*) operation. Behavior similar to the addition operation.
    • __divthe division (/) operation. Behavior similar to the addition operation.
    • __modthe modulo (%) operation. Behavior similar to the addition operation.
    • __powthe exponentiation (^) operation. Behavior similar to the addition operation.
    • __unmthe negation (unary -) operation. Behavior similar to the addition operation.
    • __idivthe floor division (//) operation. Behavior similar to the addition operation.
    • __bandthe bitwise AND (&) operation. Behavior similar to the addition operation, except that Lua will try a metamethod if any operand is neither an integer nor a float coercible to an integer (see §3.4.3).
    • __borthe bitwise OR (|) operation. Behavior similar to the bitwise AND operation.
    • __bxorthe bitwise exclusive OR (binary ~) operation. Behavior similar to the bitwise AND operation.
    • __bnotthe bitwise NOT (unary ~) operation. Behavior similar to the bitwise AND operation.
    • __shlthe bitwise left shift (<<) operation. Behavior similar to the bitwise AND operation.
    • __shrthe bitwise right shift (>>) operation. Behavior similar to the bitwise AND operation.
    • __concatthe concatenation (..) operation. Behavior similar to the addition operation, except that Lua will try a metamethod if any operand is neither a string nor a number (which is always coercible to a string).
    • __lenthe length (#) operation. If the object is not a string, Lua will try its metamethod. If there is a metamethod, Lua calls it with the object as argument, and the result of the call (always adjusted to one value) is the result of the operation. If there is no metamethod but the object is a table, then Lua uses the table length operation (see §3.4.7). Otherwise, Lua raises an error.
    • __eqthe equal (==) operation. Behavior similar to the addition operation, except that Lua will try a metamethod only when the values being compared are either both tables or both full userdata and they are not primitively equal. The result of the call is always converted to a boolean.
    • __ltthe less than (<) operation. Behavior similar to the addition operation, except that Lua will try a metamethod only when the values being compared are neither both numbers nor both strings. Moreover, the result of the call is always converted to a boolean.
    • __lethe less equal (<=) operation. Behavior similar to the less than operation.
    • __indexThe indexing access operation table[key]. This event happens when table is not a table or when key is not present in table. The metavalue is looked up in the metatable of table.

      The metavalue for this event can be either a function, a table, or any value with an __index metavalue. If it is a function, it is called with table and key as arguments, and the result of the call (adjusted to one value) is the result of the operation. Otherwise, the final result is the result of indexing this metavalue with key. This indexing is regular, not raw, and therefore can trigger another __index metavalue.

    • __newindexThe indexing assignment table[key] = value. Like the index event, this event happens when table is not a table or when key is not present in table. The metavalue is looked up in the metatable of table.

      Like with indexing, the metavalue for this event can be either a function, a table, or any value with an __newindex metavalue. If it is a function, it is called with tablekey, and value as arguments. Otherwise, Lua repeats the indexing assignment over this metavalue with the same key and value. This assignment is regular, not raw, and therefore can trigger another __newindex metavalue.

      Whenever a __newindex metavalue is invoked, Lua does not perform the primitive assignment. If needed, the metamethod itself can call rawset to do the assignment.

    • __callThe call operation func(args). This event happens when Lua tries to call a non-function value (that is, func is not a function). The metamethod is looked up in func. If present, the metamethod is called with func as its first argument, followed by the arguments of the original call (args). All results of the call are the results of the operation. This is the only metamethod that allows multiple results.

    1. local a = { 1, 2, 3, 4 }
    2. local b = { 2, 3, 4, 5 }
    3. -- 元表
    4. local mt = {};
    5. mt.__add = function(a, b)
    6. local alen = #a;
    7. local blen = #b;
    8. if alen ~= blen then
    9. print("两个表的长度不同不能相加");
    10. return;
    11. end
    12. local res = {};
    13. for i = 1, alen do
    14. res[a[i]] = a[i] + b[i];
    15. end
    16. return res;
    17. end
    18. mt.__band = function(a, b)
    19. local alen = #a;
    20. local blen = #b;
    21. if alen ~= blen then
    22. return;
    23. end
    24. local res = {};
    25. for i = 1, alen do
    26. res[i] = a[i] & b[i];
    27. end
    28. return res;
    29. end
    30. -- 元表相当于运算符重载
    31. setmetatable(a, mt);
    32. setmetatable(b, mt);
    33. local c = a + b;
    34. local d = a & b;
    35. for k, v in ipairs(c) do
    36. print(k, v);
    37. end
    38. for k, v in ipairs(d) do
    39. print(k, v)
    40. end
    41. -- 设置元表
    42. local shape = { width = 100, height = 200, x = 0, y = 0, area = 100, 4 };
    43. -- 1:在表中查找,如果找到,返回改元素,找不到继续
    44. -- 2:判断该表是否有元表,如果没有元表,返回nil,有元素就继续
    45. -- 3:判断元表有没有 __index方法,如果没有返回nil,如果__index方法是一个表,则重复1,2,3,如果__index方法是一个函数,则返回该__index函数的返回值
    46. shape.__index = function(t, key)
    47. -- for k, v in ipairs(t) do
    48. -- print(k, v);
    49. -- end
    50. print("t's len is " .. #t);
    51. print("key is " .. key);
    52. return shape[key];
    53. -- return t[key];
    54. end
    55. shape.__tostring = function(t)
    56. local res = "";
    57. print("tostring function len is " .. #t);
    58. for i = 1, #t do
    59. res = res .. t[i] .. ','
    60. end
    61. return res;
    62. end
    63. shape.__name = function(t)
    64. local res = "";
    65. for i = 1, #t do
    66. res = res .. t[i] .. ',';
    67. end
    68. print("__name res is " .. res);
    69. return res;
    70. end
    71. -- 赋值 如果元表里面没有就在元表里面插入一个新的值
    72. shape.__newindex = function(t, key, value)
    73. -- print("key is " .. key);
    74. -- print("vlaue is " .. value);
    75. shape[key] = value;
    76. end
    77. local rect = { minLeft = 0, maxLeft = 100, 7 };
    78. print(#rect);
    79. print(rawget(rect, minLeft));
    80. for k, v in ipairs(rect) do
    81. print("in rect v is k is " .. k, v);
    82. end
    83. setmetatable(rect, shape);
    84. -- print("width is " .. rect.width);
    85. -- rawget 获取一个表中是否存在key
    86. -- print(rawget(rect, width));
    87. -- 一个在元表中不存在的话会调用 __newindex 方法来对元表进行赋值
    88. -- rect.test = 100;
    89. -- print('test is ' .. rect.test);
    90. -- print("shape' test is " .. shape.test);
    91. print("----------------");
    92. print(rect);
    93. print("----------------");
    94. -- set
    95. for k, v in pairs(_G) do
    96. print(k, v);
    97. end

    二:类继承:主要用到的是元方法: __index

       self.__index = self;这句话的意思是将Cpeople的元方法__index设置为一个表,而这个表就是  Cpeople,确保能够找到对应的属性,其实__index不一定必须是函数,也可以是nil和表,对应关系如下:

    1. -- 1:在表中查找,如果找到,返回改元素,找不到继续
    2. -- 2:判断该表是否有元表,如果没有元表,返回nil,有元素就继续
    3. -- 3:判断元表有没有 __index方法,如果没有返回nil,如果__index方法是一个表,则重复1,2,3,如果__index方法是一个函数,则返回该__index函数的返回值
    1. local Cpeople = { name = "lck", age = 12 };
    2. -- Cpeople.new = function(o)
    3. -- local o = o or {};
    4. -- setmetatable(o, Cpeople);
    5. -- Cpeople.__index = Cpeople;
    6. -- return o;
    7. -- end
    8. -- local p1 = Cpeople.new();
    9. -- print(p1.name);
    10. -- : 的作用省略Cpeople
    11. function Cpeople:new(o)
    12. o = o or {};
    13. setmetatable(o, self);
    14. self.__index = self;
    15. return o;
    16. end
    17. function Cpeople:walk()
    18. print(self.name .. " walking");
    19. end
    20. local p1 = Cpeople:new();
    21. print(p1.name, p1.age);
    22. p1:walk();
    23. -- 男性继承自人类
    24. Male = {}
    25. function Male:new(o)
    26. local o = o or {};
    27. setmetatable(o, self);
    28. self.__index = self;
    29. -- 继承 people
    30. setmetatable(self, Cpeople);
    31. Cpeople.__index = Cpeople;
    32. return o;
    33. end
    34. local p2 = Male:new({ name = "ddd" });
    35. p2:walk();
    36. return Cpeople;

     

  • 相关阅读:
    HTTPS内容详解(图解HTTP协议)
    RSA加密解密详解
    高性能同轴高清 ISP芯片XS5012A参数
    Go Mutex(互斥锁)
    腾讯T9纯手写基于Mycat中间件的分布式数据库架构笔记
    Vue的过滤器(filter)
    C# --- 面向对象六大原则
    设计模式:适配器模式(C++实现)
    【毕业设计源码】基于JAVA的团员信息管理系统的设计与实现
    企业实施ERP系统遇到的问题及应对措施
  • 原文地址:https://blog.csdn.net/lck8989/article/details/127616832