Lua学习记录 — (10)面向对象-类(公有私有属性/静态,重写,运算符重载,继承等等)
2018-02-04 01:41
561 查看
BjaClass类模拟包——点击下载
ObjectOriented.lua
BjaClass类模拟包——点击下载
BjaClassExample.lua
ObjectOriented.lua
------------------------------------ Lua面向对象 ------------------------------------ -- Lua中没有直接的类定义方法;(需要通过模拟来实现) -------------------- 类的封装 -------------------- -- Lua中的类可以通过 table 来模拟实现; do --- 构建类表(每个对象都将类表设置为元表,类表中的对象都是静态的) BaseClass = {} BaseClass.__index = BaseClass -- 此步骤当BaseClass作为元表时,能够基表访问到(否则静态属性无法访问); BaseClass.__newindex = function(object,k,v) -- 此步骤使通过obj更改ClassA的静态变量时,能够作用在ClassA上(否则只能通过BaseClass.静态名 = xxx 更改静态变量); -- 这么处理是避免obj操作非静态变量时,直接作用在BaseClass表上; if BaseClass[k] then -- 当Class上存在k键时,说明这个是静态变量; BaseClass[k] = v else -- 否则,则操作对象obj自身的成员; rawset(object,k,v) end end -- 创建对象私有表 BaseClass.createPrivateTable = function(object) local private = {} -- 元表索引向基类对象的private表,索引更新也指向基类对象的private表(避免更新数据时,重复创建private数据) setmetatable(private,{__index = object.private,__newindex = object.private}) object.private = private return private end --- 构建类元表(如果不继承,可以不构建元表,构造器使用 BaseClass:new() 来定义) local Class_MT = {} setmetatable(BaseClass,Class_MT) -- 此处元表作用:1.继承;2.创建Class()形式的构造器 -- 无继承 Class_MT.__index = {} --- 构造器(利用了元方法,以实现Class()格式即可创建对象) Class_MT.__call = function(tbl,arg) --- 创建BaseClass的对象(函数结束一定要返回它) local obj = {} local private = BaseClass.createPrivateTable(obj) setmetatable(obj,BaseClass) --- 私有成员(通过闭包的性质实现) -- 属性 private._privateMember = "BaseClass privateMember" -- 方法(私有方法没什么意义,可以用公有替代) private._privateFunc = function() print("BaseClass 调用了私有函数,本对象的arg = " .. obj.arg) end --- 公有成员(每个obj都会生成各自对应的成员) -- 属性 obj.publicMember = "BaseClass publicMember" obj.arg = arg or 0 --- 返回对象 return obj end --- 静态属性 -- 公有(内外部都可以直接通过 "类名.静态名" 访问静态属性了) BaseClass.publicStaticMember = "BaseClass publicStaticMember" -- 私有(内部直接使用 "静态名" 访问私有静态) local privateStaticMember= "BaseClass privateStaticMember" --- 静态方法 -- 公有(不能访问对象的成员) BaseClass.publicStaticFunc = function() print("这里是 BaseClass 公有静态函数") end -- 私有 local privateStaticFunc = function() print("这里是 BaseClass 私有静态函数") end --- 公有 函数成员 -- 操作公有成员属性(只用到公有成员的情况下,这种方法较好,每个obj共用一个函数,较少占内存) function BaseClass:ShowPublicMember() if BaseClass == self then error("不可通过Class名直接访问成员,请使用对象访问") return end print(self.publicMember) end -- 方法:获取私有属性() function BaseClass:getPrivateMember() return self.private._privateMember end -- 方法:设置私有属性() function BaseClass:setPrivateMember(str) self.private._privateMember = str end -- 方法:调用私有函数 function BaseClass:publicFunc() print("BaseClass 调用了公有函数,本对象的arg = ".. self.arg .. "接下来调用私有函数:") self.private._privateFunc() end --- 运算符重载 -- 重载加号 BaseClass.__add = function(obj1,obj2) if obj1 == BaseClass or obj2 == BaseClass then error("不可直接对BaseClass类作加法运算,请使用对象操作") return end return obj1.arg + obj2.arg end end -------------------- 封装测试 do print("==================== 《封装测试》 ====================") -- 创建对象objA local objA = BaseClass(1) print("\n=====objA基本成员属性展示=====") --> =====objA基本成员属性展示===== -- 展示对象的成员 print(objA.publicMember) --> BaseClass publicMember -- 调用对象的函数 objA:publicFunc() --> BaseClass 调用了公有函数,本对象的arg = 1接下来调用私有函数: -- 通过公有函数获取私有成员 BaseClass 调用了私有函数,本对象的arg = 1 str = "这个是改变前的私有成员属性:%s" print(str:format(objA:getPrivateMember())) --> 这个是改变前的私有成员属性:BaseClass privateMember -- 通过公有函数改变私有成员,再展示 objA:setPrivateMember("objA BaseClass privateMember") str = "这个是改变后的私有成员属性:%s" print(str:format(objA:getPrivateMember())) --> 这个是改变后的私有成员属性:objA BaseClass privateMember -- 创建对象objB local objB = BaseClass(3) -- 上面改变了objA的私有成员,现在访问objB的私有成员(不冲突) print("\n=====objA的私有成员已改变,现在访问objB的私有成员=====") --> =====objA的私有成员已改变,现在访问objB的私有成员===== str = "objA的私有变量:%s,objB的私有变量:%s" print(str:format(objA:getPrivateMember(),objB:getPrivateMember())) --> objA的私有变量:objA BaseClass privateMember,objB的私有变量:BaseClass privateMember -- 改变objA的公有成员,再访问objB的公有成员(不冲突) print("=====接着改变objA的公有成员,再访问objB的公有成员=====") --> =====接着改变objA的公有成员,再访问objB的公有成员===== objA.publicMember = "objA BaseClass publicMember" str = "objA的公有变量:%s,objB的公有变量:%s" print(str:format(objA.publicMember,objB.publicMember)) --> objA的公有变量:objA publicMember,objB的公有变量:BaseClass publicMember -- 访问BaseClass静态成员 print("\n=====BaseClass静态成员测试=====") --> =====BaseClass静态成员测试===== print("更改前 " .. BaseClass.publicStaticMember) --> 更改前 BaseClass publicStaticMember BaseClass.publicStaticMember = "new publicStaticMember" print("更改后 " .. objA.publicStaticMember) --> 更改后 new publicStaticMember objA.publicStaticMember = 123 print("通过对象更改后 " .. objB.publicStaticMember) --> 通过对象更改后 objA publicStaticMember BaseClass.publicStaticFunc() --> 这里是 BaseClass 公有静态函数 objB.publicStaticFunc() --> 这里是 BaseClass 公有静态函数 -- 运算符重载 print("\n=====BaseClass运算符重载测试=====") --> =====BaseClass运算符重载测试===== print("objA + objB = " .. objA+objB) --> objA + objB = 4 end -------------------- 类的继承 -------------------- -- 可以通过metatable元表的__index来模拟实现; do --- 构建类表 DerivedClass = {} DerivedClass.__index = DerivedClass -- 此步骤当DerivedClass 作为元表时,能够基表访问到(否则静态属性无法访问); DerivedClass.__newindex = function(object,k,v) -- 此步骤使通过obj更改DerivedClass的静态变量时,能够作用在DerivedClass上(否则只能通过DerivedClass.静态名 = xxx 更改静态变量); -- 这么处理是避免obj操作非静态变量时,直接作用在BaseClass表上; if DerivedClass[k] then -- 当Class上存在k键时,说明这个是静态变量; DerivedClass[k] = v else -- 否则,则操作对象obj自身的成员; rawset(object,k,v) end end -- 创建对象私有表 DerivedClass.createPrivateTable = function(object) local private = {} -- 元表索引向基类对象的private表,索引更新也指向基类对象的private表(避免更新数据时,重复创建private数据) setmetatable(private,{__index = object.private,__newindex = object.private}) object.private = private return private end --- 构建类元表 local Class_MT = {} setmetatable(DerivedClass,Class_MT) -- 此处元表作用:1.继承;2.创建Class()形式的构造器 -- 继承BaseClass Class_MT.__index = BaseClass --- 构造器(利用了元方法,以实现Class()格式即可创建对象) Class_MT.__call = function(Class,arg) --- 创建ClassA的对象(函数结束一定要返回它) local obj = BaseClass(arg) local private = DerivedClass.createPrivateTable(obj) setmetatable(obj,DerivedClass) --- 重写私有属性 private._privateMember = "DerivedClass privateMember" --- 重写公有属性 obj.publicMember = "DerivedClass publicMember" obj.arg = arg or 0 --- 返回对象 return obj end --- 新的静态变量 DerivedClass.newPublicStaticMember = "DerivedClass newPublicStaticMember" --- 重写公有方法 function DerivedClass:publicFunc() print("DerivedClass 调用了公有函数,本对象的arg = ".. self.arg .. "接下来调用私有函数:") self.private._privateFunc() end --- 运算符重载(重载运算符无法继承) -- 重载减号 DerivedClass.__sub = function(obj1,obj2) if obj1 == BaseClass or obj2 == BaseClass then error("不可直接对BaseClass类作加法运算,请使用对象操作") return end return obj1.arg - obj2.arg end end -------------------- 继承测试 do print("\n\n==================== 《继承测试》 ====================") -- 创建对象objA local objA = DerivedClass(5) print("\n=====objA基本成员属性展示=====") --> =====objA基本成员属性展示===== -- 展示对象的成员 print(objA.publicMember) --> DerivedClass publicMember -- 调用对象的函数 objA:publicFunc() --> DerivedClass 调用了公有函数,本对象的arg = 5接下来调用私有函数: -- 通过公有函数获取私有成员 BaseClass 调用了私有函数,本对象的arg = 5 str = "这个是改变前的私有成员属性:%s" print(str:format(objA:getPrivateMember())) --> 这个是改变前的私有成员属性:DerivedClass privateMember -- 通过公有函数改变私有成员,再展示 objA:setPrivateMember("objA DerivedClass privateMember") str = "这个是改变后的私有成员属性:%s" print(str:format(objA:getPrivateMember())) --> 这个是改变后的私有成员属性:objA DerivedClass privateMember -- 创建对象objB local objB = DerivedClass(3) -- 上面改变了objA的私有成员,现在访问objB的私有成员(不冲突) print("\n=====objA的私有成员已改变,现在访问objB的私有成员=====") --> =====objA的私有成员已改变,现在访问objB的私有成员===== str = "objA的私有变量:%s,objB的私有变量:%s" print(str:format(objA:getPrivateMember(),objB:getPrivateMember())) --> objA的私有变量:objA DerivedClass privateMember,objB的私有变量:DerivedClass privateMember -- 改变objA的公有成员,再访问objB的公有成员(不冲突) print("=====接着改变objA的公有成员,再访问objB的公有成员=====") --> =====接着改变objA的公有成员,再访问objB的公有成员===== objA.publicMember = "objA DerivedClass publicMember" str = "objA的公有变量:%s,objB的公有变量:%s" print(str:format(objA.publicMember,objB.publicMember)) --> objA的公有变量:objA DerivedClass publicMember,objB的公有变量:DerivedClass publicMember -- 访问BaseClass静态成员 print("\n=====DerivedClass静态成员测试=====") --> =====DerivedClass静态成员测试===== print("更改前 " .. DerivedClass.publicStaticMember) --> 更改前 123 DerivedClass.publicStaticMember = "new publicStaticMember" print("更改后 " .. objA.publicStaticMember) --> 更改后 new publicStaticMember objA.publicStaticMember = 999 print("通过对象更改后 " .. objB.publicStaticMember) --> 通过对象更改后 999 print("BaseClass的静态成员 " .. BaseClass.publicStaticMember) --> BaseClass的静态成员 123 DerivedClass.publicStaticFunc() --> 这里是 BaseClass 公有静态函数 objB.publicStaticFunc() --> 这里是 BaseClass 公有静态函数 print(DerivedClass.newPublicStaticMember) --> DerivedClass newPublicStaticMember -- 运算符重载(重载运算符无法继承) print("\n=====BaseClass运算符重载测试=====") --> =====BaseClass运算符重载测试===== print("objA - objB = " .. objA-objB) --> objA + objB = 2 end ----- 类的多态 -- Lua中模拟的类天然支持多态 do print("\n\n==================== 《多态测试》 ====================") local base = BaseClass(5) local Derived = DerivedClass(10) base:publicFunc() --> BaseClass 调用了公有函数,本对象的arg = 5接下来调用私有函数: -- BaseClass 调用了私有函数,本对象的arg = 5 base = Derived base:publicFunc() --> DerivedClass 调用了公有函数,本对象的arg = 10接下来调用私有函数: -- -- BaseClass 调用了私有函数,本对象的arg = 10 end
BjaClass类模拟包——点击下载
BjaClassExample.lua
-------------------- 完整的类(示例)-------------------- BjaClass = require("BjaClass") do --- 创建一个类(作为基类) People = BjaClass.MakeClass() --- 创建构造器 local cotr = function(class,name,age,id) --- 创建对象(函数结束一定要返回它) local obj = BjaClass.MakeObj(class) People.counter = People.counter + 1 --- 公有成员 obj.name = name or "none" obj.age = age or 0 --- 私有成员 obj.private._tag = "peop" obj.private._id = id or People.counter --- 返回对象 return obj end BjaClass.MakeCtor(People,cotr) --- 静态变量 People.counter = 0 -- 公有 People.privateStatic._type = "people" -- 私有 --- 静态方法 People.ShowCount = function(self)print("People 的数量是 " .. self.counter) end -- 公有 People.GetType = function(self)return self.privateStatic._type end -- 公有 --- 公有成员方法 function People:introduce() if self == People then error("不能通过类直接调用非静态成员!") return nil end local format = "我叫%s,今年%d岁!" print(format:format(self.name,self.age)) end function People:getId() if self == People then error("不能通过类直接调用非静态成员!") return nil end return self.private._id end function People:getTag() if self == People then error("不能通过类直接调用非静态成员!") return nil end return self.private._tag end --- 运算符重载 People.__add = function(obj1,obj2) if obj1.age and obj2.age then return obj1.age + obj2.age end return nil end People.__lt = function(obj1,obj2) local num1,num2 = 0,0 if type(obj1)=="number" then num1 = obj1 else num1= obj1.age end if type(obj2)=="number" then num2 = obj2 else num2= obj2.age end return (num1 < num2) end end do --- 创建一个类(派生至People) Programmer = BjaClass.MakeClass(People) --- 创建构造器 local cotr = function(class,name,age,id) --- 创建对象(函数结束一定要返回它) local obj = BjaClass.MakeObj(class,name,age,id) --- 公有成员 obj.career = "Unity3D程序员" --- 重写私有成员 obj.private._tag = "prog" --- 返回对象 return obj end BjaClass.MakeCtor(Programmer,cotr) --- 重写静态变量 Programmer.privateStatic._type = "programmer" -- 私有 --- 重写公有成员方法 function Programmer:introduce() if self == Programmer then error("不能通过类直接调用非静态成员!") return nil end local format = "我叫%s,今年%d岁,是一名%s!" print(format:format(self.name,self.age,self.career)) end end do print("\n\n==================== 《示例测试》 ====================") print("(1)") boy = People("BeiJiaan",25) boy:introduce() --> 我叫BeiJiaan,今年25岁! People:ShowCount() --> People 的数量是 1 print("People的Type = " .. boy:GetType()) --> People的Type = people print("boy的Id = " .. boy:getId()) --> boy的Id = 1 print("boy的Tag = " .. boy:getTag()) --> boy的Tag = peop print("(2)") beijiaan = Programmer("贝哥哥",25) beijiaan:introduce() --> 我叫贝哥哥,今年25岁,是一名Unity3D程序员! Programmer:ShowCount() --> People 的数量是 2 print("Programmer的Type = " .. beijiaan:GetType()) --> Programmer的Type = programmer print("beijiaan的Id = " .. beijiaan:getId()) --> beijiaan的Id = 2 print("beijiaan的Tag = " .. beijiaan:getTag()) --> beijiaan的Tag = prog print("(3)") print("boy's age + beijiaan's age = " .. boy + beijiaan) --> boy's age + beijiaan's age = 50.0 print("beijiaan's age + boy's age = " .. beijiaan + boy) --> beijiaan's age + boy's age = 50.0 print("boy's age > 30? " .. tostring(boy > 30)) --> boy's age < 30? false print("beijiaan's age > 30? " .. tostring(beijiaan > 30)) --> 报错!!!attempt to compare number with table end
相关文章推荐
- JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
- 第174天:面向对象——公有属性、私有属性和静态属性
- js面向对象之公有、私有、静态属性和方法详解
- js面向对象之公有、私有、静态属性和方法详解
- C++学习笔记4--静态属性 静态方法 虚方法 抽象方法 多态性 析构函数 运算符重载 多继承 虚继承
- js面向对象之公有、私有 、静态方法和属性,以及特权方法
- JS面向对象(3)之Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
- ExtJs--10--Ext定义类时,别名 备用名 和 静态属性 可继承静态属性的学习
- js面向对象之公有、私有、静态属性和方法详解
- js面向对象之公有、私有、静态属性和方法详解
- JS面向对象(3)之Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法
- swift 学习记录(静态属性)
- JavaScript面向对象-静态方法-私有方法-公有方法-特权方法
- js公有、私有、静态属性和方法
- C# 类,私有公有属性,继承
- js 对象方法、类方法、原型方法的区别;私有属性、公有属性、公有静态属性的区别
- js公有、私有、静态属性和方法的区别
- Lua和C++交互 学习记录之九:在Lua中以面向对象的方式使用C++注册的类
- JavaScript面向对象-静态方法-私有方法-公有方法-特权方法
- 8 面向对象(制作帮助文档,通过JDK提供的API学习了Math类,代码块,继承(继承子父成员访问特点,super关键字,方法重写))