end
Account.withdraw(100.00) -- ok.
a, Account = Account, nil
a.withdraw(100.00) -- ERROR! -- becuase we hard code the global name:Account
----------second version
function Account.withdraw (self, v) -- YouYou--Notice that , we need to pass selft parameter.
self.balance = self.balance - v -- we use self
end
a1 = Account; Account = nil
...
a1.withdraw(a1, 100.00) -- OK -- YouYou--Notice that , we need to pass a1 as selft parameter.
-----------third version
Lua also can hide this parameter, using the colon operator. We can rewrite the previous method definition as
function Account:withdraw (v) -- no need to pass self
self.balance = self.balance - v
end
and the method call as
a:withdraw(100.00) -- no need to pass a into the method.
--------4th version version
Account =
{ balance=0,
withdraw = function (self, v) --在里面定义的话,就必须自己加self as the first parameter
self.balance = self.balance - v
end
}
function Account:deposit (v)
self.balance = self.balance + v
end
16.1 Classes
Lua does not have the concept of class; each object defines
its own behavior and has a shape of its own. Nevertheless, it is not difficult to
emulate classes in Lua, following the lead from prototype-based languages like
Self and NewtonScript.
In these languages, objects have no classes. Instead,
each object may have a prototype, which is a regular object (,同样prototype also not class , )it's an object where the first object looks up any operation that it does not know about (这也是我中午联想到的), 在自己的定义里面没找到就找prototype, 1st prototype not found ,then prototyp's prototypes etc,,,,,
RootA={
A=10;
}
RootB={
B=20;
}
RootC={
C=30;
}
setmetatable(RootB,{__index=RootA});
setmetatable(RootC,{__index=RootB});
print("Test Root finding",RootC.A); -- 10 ,,这里证明recursive works, 这就给面向对象的模仿带来可能了
To represent a class in
such languages, we simply create an object to be used exclusively as a prototype
for other objects (its instances). Both classes and prototypes work as a place to
put behavior to be shared by several objects. 这个prototype 就当所有对象的RootClass Object.,, any object must
directly or 非直接的继承于他 ,,,,,(这也是我目前知道的,,,)
============
RootObjectClass={
name="RootObjectClass";
}
--setmetatable(RootObjectClass,{__index=RootObjectClass}); 会进入dead loop
function RootObjectClass:new(o)
o=o or {};
setmetatable(o,self);
self.__index=self; -- I just set the new ojbect o's metable to RootObjectClass, but I did not set RootObjectClass's metatable, Notice this different
return o;
end
function RootObjectClass:getName()
return self.name;
end
mya=RootObjectClass:new({name="MyA Name"});
myb=RootObjectClass:new();
print(mya:getName());
print(myb:getName());
======= result====
MyA Name -- 可以看到因为self 的使用我们得到的面向对象的特性,即使我们使用的getName method is define in root
RootObjectClass
========
16.2 Inheritance
RootObjectClass={
className="RootObjectClass";
}
--setmetatable(RootObjectClass,{__index=RootObjectClass}); 会进入dead loop
function RootObjectClass:new(o)
o=o or {};
setmetatable(o,self);
self.__index=self; -- I just set the new ojbect o's metable to RootObjectClass, but I did not set RootObjectClass's metatable, Notice this different
return o;
end
function RootObjectClass:getClassName()
return self.className;
end
Person=RootObjectClass:new({className="Person"});
function Person:Eat()
print("I am a"..self.className.." eating..."); --Notice:do't foget to write self.
end
function Person:Sleep()
print("I am a "..self.className.." sleeping.."); --Notice:do't foget to write self.
end
Student=Person:new({className="Student"}); -- not RootObjectClass:new, orelse,will directly inheritance from RootObjectClass
function Student:Learning()
print("haha I am a "..self.className.." Learing"); --Notice:do't foget to write self.
end
Student 继承 Person ,and Person inherite RootObjectClass
s=Student; // here we can't write like: Student s=new Student and like, becuase Student is a Object not a class, not
//the real OO language.
s:Eat(); --I am aStudent eating...
16.3 Multiple Inheritance
The key to this implementation is the use of a function for the metafield
__index. Remember that, when a table’s metatable has a function in the __index
field, Lua will call this function whenever it cannot find a key in the original
table. Then, __index can look up for the missing key in how many parents it
wants.
Root1ObjectClass={
className="RootObject1Class";
}
Root2ObjectClass={
className="RootObject2Class";
}
local function search(parentList,key)
for i=1,#parentList do --害死我拉,,, in lua the start index of a table is from 1 ,not from 2.
local v=parentList[i][key]
if v then
return v;
end
end
end
function createClass(...) 需要创建一个多个基类的模板
local multipleClassTemplate={};
local multiparent={...}; -- we just use a singel table to contain all it's supper class
setmetatable(multipleClassTemplate,{
__index=function(o,key)
return search(multiparent,key);
end
});
function multipleClassTemplate:new(o)
o=o or {};
setmetatable(o,multipleClassTemplate);
multipleClassTemplate.__index=self;
return o;
end
return multipleClassTemplate;
end
function Root1ObjectClass:getClassName1()
print("Root1ObjectClass:getClassName1");
return self.className;
end
function Root2ObjectClass:getClassName2()
print("Root2ObjectClass:getClassName2");
return self.className;
end
MultleClass=createClass(Root1ObjectClass,Root2ObjectClass);
obj=MultleClass:new(); -- obj is inherite from 2 object
print(obj:getClassName1());
print(obj:getClassName2()); --Root2ObjectClass:getClassName2(), but when call return self.className; calssName will locate at the Root1ObjectClass, becuase of the search
Of course, due to the underlying complexity of this search, the performance
of multiple inheritance is not the same as single inheritance. A simple way
to improve this performance is to copy inherited methods into the subclasses.
Using this technique, the index metamethod for classes would be like this:
setmetatable(c, {__index = function (t, k)
local v = search(k, parents)
t[k] = v -- save for next access
return v
end})
--都不知道这些继承有多大的用处,,,,
16.4 Privacy
解决的办法是分开2 table, one to store it's variable, second is it's operation. operation is public, and variable is private, we just return table 2,but for table1 we use closure
function newAccount (initialBalance)
local self = {balance = initialBalance} --first table. keep's variable,not expose self,
local withdraw = function (v)
self.balance = self.balance - v -- self will keep in the enclosure env
end
local deposit = function (v)
self.balance = self.balance + v
end
local getBalance = function () return self.balance end
return { -- we just return the 2nd table,
withdraw = withdraw,
deposit = deposit,
getBalance = getBalance
}
end
This design gives full privacy to anything stored in the self table. After
newAccount returns, there is no way to gain direct access to this table.
麻烦死了,,,