chapter 16 Object-Oriented Programming

Account = {balance = 0}
function Account.withdraw (v)
Account.balance = Account.balance - v , 在 函数里面我们hardcode the global name : Account,bad pratice.

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.


麻烦死了,,,



























































  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值