Object-oriented programming in LUA

Source: Internet
Author: User
Tags lua

A brief talk about object-oriented in Lua

The table in Lua is an object that looks at the following simple code:

The above code will output TB1 ~= TB2. Note that two objects that have the same worth are two different, while the table in Lua is a reference type. As I've also summarized in the modules and packages in Lua, we are a table-based module that allows you to define functions in a table, meaning that each Table object can have its own operations. Look at the code:

The code above creates a new function and stores it in the withdraw field of the account object, and then we can call the function. However, using the global name in a function account is a bad programming habit because the function can only work on a specific object, and this particular object must also be stored in a particular global variable. If you change the name of the object, withdraw will no longer work. For example, the following code:

This will cause an error. Here I use account to create a new object A, and when the account is assigned to nil, it should have no effect on the A object. However, an error occurred because the account was used inside the function withdraw instead of the variable A. If we modify the Account.balance = Account.balance–v statement inside the withdraw function to: A.balance = A.balance–v, there will be no error. This shows that when we need to operate on a function, we need to specify the actual operand, that is, a here, which requires an additional parameter to represent the operator, just like this in C + +, but this keyword is changed to self, the following code after the change:

If you do so again, there will be no error.

Using the self parameter is a core of all object-oriented languages. Most object-oriented languages hide the self parameter from the programmer, so that the programmer does not have to declare the parameter as shown. Lua can also, when we are defining a function, using a colon, we can hide the argument, then the above code using a colon to change, this is the way it is.

The colon acts simply by adding an extra hidden parameter to the method definition and adding an extra argument to a method call. The colon is simply a grammatical convenience, and does not introduce anything new; If you want, you can do it without self, but in each definition of a function, manually add self, as long as you handle self, they are all the same.

There's a lot of talk about Lua, but it's mostly about the table being a different thing and self. Next, we formally enter the object-oriented world. Do not forget that the above summarizes the things that are very useful.

Class

What is a class? A class is a stencil that creates objects. For example, in C + +, each object is an instance of a particular class. In C + +, if a class is not instantiated, then the corresponding operation in this class is basically a bunch of "useless" code, and Lua is not the same, even if you do not instantiate a "class", you can also use the "class" name directly call its method (for C + +, ignore the static method) This shows that the concept of "class" in Lua differs from the concept of a class in a high-level language such as C + +. There is no class concept in Lua, and we are all using Lua's existing support to emulate the concept of classes. In Lua, to represent a class, you simply create a prototype (prototype) dedicated to other objects. Prototypes are also a regular object, which means that we can invoke the corresponding method directly from the prototype. When another object (an instance of the class) encounters an unknown operation, the prototype looks for it first.

It is very simple to implement a prototype in Lua, such as having two objects A and b, and for B to be a prototype, it can be done with the following code:

Once this code is set, a will look in B for all the actions it does not have. If B is referred to as the "class" of object A, it is merely a change in terminology. Now I start from the simplest, to create an instance object, you must have a prototype, called the "class", see the following code:

Well, now that we have a prototype, how do you use this prototype to create an "instance"? Then look at the following code:

When Account:new is called, Self is equivalent to account. Next, we can call Account:new to create an instance. Look again:

How does this piece of code work? First, a new instance object is created with Account:new and the account is used as a meta-table of the new instance object A. And then when we call the A:display function, it's the equivalent of A.display (a), and the colon is just a "syntactic sugar", just a handy notation. We created an instance object A, and when we called display, we looked for the display field in a, and then we searched its meta-table, so the final call was as follows:

A's meta-table is Account,account's __index is also account. Therefore, the above call can also make such a:

So, what we can actually see is that the instance object in table A does not have the display method, but inherits from the account method, but the self in the incoming display method is indeed a. This allows the account (the "class") to define the operation. In addition to the method, a can inherit all the fields from account.

Inheritance can be used not only for methods, but also for fields. Therefore, a class can provide not only methods, but also default values for the fields in the instance. Look at the following code:

There is a value field in the Account table with a default value of 0, and when I create an instance object A, the value field is not provided, and in the display function, the meta-table account is found because there is no value field in a. Finally, the value of value in account is obtained, and the value of Self.value to the right of the equal sign is derived from value in account. When calling A:display (), the following code is actually called:

In the definition of display, it will look like this:

The first time you call display, The Self.value on the left side of the equal sign is a.value, which is equivalent to adding a new field value to a, and when the display function is called the second time, because the value field is already in a, the value field is not searched for in the account.

Inherited

Because classes are also objects (exactly a prototype), they can also derive (inherit) methods from other classes (prototypes). This behavior is inheritance and can be easily implemented in Lua. Now we have a class (the prototype, in fact, in Lua said the concept of class, or very awkward, after all, with C + + 's head to think, or feel a little strange. ) CA:

Now that you need to derive a subclass of Clittlea from this CA class, you need to create an empty class that inherits all the operations from the base class:

Now, I've created an instance object of a CA class, in Lua, now Clittlea is both an instance object of the CA class and a prototype, the so-called class, which is equivalent to the Clittlea class inheriting from the CA class. Again, as in the following code:

Clittlea inherits new from the CA, however, when Clittlea:new is executed, its self parameter is represented as Clittlea, so the value of the field Clittlea,clittlea in the metatable of S is __index. Then we'll see that s inherits from Clittlea, and Clittlea inherits from the CA. When S:display is executed, LUA does not find the display field in S, it looks for Clittlea, and if the display field is still not found, the CA is found, and the display field is eventually located in the CA. Think of this, if there is a display field in the Clittlea, then you will not go to the CA to find it. So we can redefine the display field in Clittlea to implement a special version of the display function.

Multiple inheritance

When it comes to multiple inheritance, I also use very little in writing C + + code, generally using a combination of ways to solve, for the "combination" this concept does not understand a friend, you can read my design pattern series of articles. Now that you've talked about multiple inheritance in Lua, that's a summary, by the way, to broaden your horizons and knowledge.

When you implement single inheritance, you rely on setting metatable for subclasses, setting their metatable as the parent class, and setting the __index of the parent class to its own technology implementation. And multiple inheritance is the same truth, in single inheritance, if there is no corresponding field in the subclass, it is only necessary to look for the nonexistent field in a parent class, and in multiple inheritance, if the subclass does not have a corresponding field, you need to look for the nonexistent field in multiple parent classes.

As a representation, LUA searches the display field one at a multiple parent class. In this way, we cannot directly specify __index as a parent class, as in single inheritance, but should specify __index as a function in which to specify rules for searching for fields that do not exist. This allows for multiple inheritance. There are two issues that need to be solved:

    1. Save all the parent classes;
    2. Specify a search function to complete the search task.

For the multiple inheritance above, let's look at a headache code:

-- Find fields in multiple parent classesKLocal functionSearch(K,Pparentlist) ForI= 1, #pParentList do LocalV=Pparentlist[I][K] IfVThen ReturnVEnd EndEndfunctionCreateclass(...) LocalC= {} -- New class LocalParents= {...} -- class to search for methods in its meta-tableSetmetatable(C, {__index= function (T,K) ReturnSearch(K,Parents) End}) -- WillCAs the metatable of its instanceC.__index=C-- Create a new constructor for this new class functionC:New(O)O=OOr {}Setmetatable(O, Self) -- Self.__index= Self It's not set up, it's already set up on theC.__index=CReturnOEnd -- Return a new Class (prototype) ReturnCEnd-- A simple classCaLocalCa= {}functionCa:New(O)O=OOr {}Setmetatable(O, {__index= Self}) Self.__index= Self ReturnOEndfunctionCa:SetName(StrName) Self.Name=StrNameEnd-- A simple classCbLocalCb= {}functionCb:New(O)O=OOr {}Setmetatable(O, Self) Self.__index= Self ReturnOEndfunctionCb:GetName() Return Self.NameEnd-- Create aCClass, which is the parent class of theCaAndCbLocalC=Createclass(Ca,Cb)-- UseCClass to create an instance objectLocalObjectc= C:new{ name =  "Jelly" }--  set OBJECTC  object a new name objectc:setname  ( "Jellythink" ) local< Span class= "PLN" > NewName = Objectc: () print ( Newname              

The code is a headache, but it continues to look. First of all, read the above code, do not understand it does not matter. Now let me explain the above code.

    1. A class (prototype) is created using Createclass, and the CA and CB are set to the parent class (prototype) of this class (archetype), and in the class (prototype) that is created, the __index of the class is set to a search function. In this search function, look for fields that are not in the created class;
    2. In the new class created, there is a constructor new; This new is not the same as the new one in the previous single inheritance, very well understood;
    3. Call the new constructor to create an instance object that has a name field;
    4. Call Object:setname ("Jellythink") statement, set a new name, but do not have this field in OBJECTC? OK, go to the parent class, first go to the CA to find, all of a sudden found, and then called the Setname,setname in the self point is objectc; After setting, it is equivalent to modifying the name value of the OBJECTC field;
    5. Call Objectc:getname (), OBJECTC still does not have this field. Find, CA also did not, then go to find, in the CB found, call GetName, in GetName in the self point is OBJECTC. Therefore, the value of name in OBJECTC is returned in Objectc:getname, which is "Jellythink".

What else? Nothing, for multiple inheritance, seemingly difficult to look, very troublesome, in fact, it is so little things. If you don't understand, do it again.

What do I have to protect you?

As we all know, in C + + or Java, you have access to member functions or variables in a class. Public,protected and private These key words also know it. Well, what about LUA? Lua is itself a "simple" scripting language, itself is not for large projects, so, its language characteristics, itself does not carry these things, if you want to use such protection of things, what to do? We are still "curve the salvation". The idea is to represent an object by a two table. One table is used to hold the object's private data, and the other for the object's operation. The actual operation of the object is implemented by a second table. To avoid unauthorized access, the table that holds the private data for the object is not saved in the other table, but only in the closure of the existing method. Look at the code:

This design gives full privacy to everything stored in the self table. This table cannot be accessed directly when the call to NewObject is returned. This self table can only be accessed through the functions created in NewObject, which is equivalent to the private one stored in the Self table, which cannot be accessed directly from outside. As you may have noticed, I did not use a colon when I visited the function, which is mainly because I can directly access the fields in the Self table, so I don't need the extra self field, and I don't have a colon.

Object-oriented programming in LUA

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.