ESOUI

ESOUI (https://www.esoui.com/forums/index.php)
-   General Authoring Discussion (https://www.esoui.com/forums/forumdisplay.php?f=174)
-   -   ZO_Object (https://www.esoui.com/forums/showthread.php?t=4855)

kerb9729 07/02/15 10:21 AM

ZO_Object
 
Hey guys,

New developer here. I've been looking at some existing addons, figuring out how they work as a learning exercise. Which brings me to my question:

I'm confused about ZO_Object. What is the benefit of using it?

Atropos 07/02/15 10:43 AM

I've been working on ESO addons since the very beginning and I still have big gaps in understanding about this.

There's a lot of things floating in the API that try and objectify LUA tables, but I'm not entirely clear what you actually GAIN by using this.

I'll stay tuned to see if you get any gurus in here to enlighten us.

merlight 07/02/15 11:05 AM

It provides the basis for class inheritance. http://esodata.uesp.net/current/src/...bject.lua.html

kerb9729 07/02/15 11:34 AM

Quote:

Originally Posted by merlight (Post 21817)
It provides the basis for class inheritance. http://esodata.uesp.net/current/src/...bject.lua.html

I guess one of the drawbacks in learning from existing addon code is that I can't always be sure that what I'm looking at is the "right" way of doing things.

I wonder if someone would be willing to show me an example of the correct way to use ZO_Object?

Do I create a template using ZO_Object.SubClass and then instantiate an object from it using
myobject = ZO_Object.New(templateIcreated)?

That seems like it should be correct, but I don't see it done that way (in the addons I've looked at thus far)?

sirinsidiator 07/02/15 01:35 PM

I don't now the *right* way to do things in Lua, as I only learned it since I started to make ESO addons and mostly by looking at the code of the ingame UI, but I quite like the ZO_Object way. It makes things resemble the other languages that I work with every day. Switching between multiple different programming languages is a pain if everything looks and works completely different.

I could do everything without it, but it allows me to structure code like in other languages.

XanDDemoX 07/02/15 02:08 PM

I use a slightly different function for class inheritance which requires a little less typing but it is essentially equivalent to ZO_Object :)

Code:


local function class(base)

        local c = {}
       
        if type(base) == "table" then
                for k,v in pairs(base) do
                        c[k]=v
                end
                c.base = base
        end
       
        c.__index = c
       
        setmetatable(c,{ __call=function(self,...)

              -- create instance
                local obj = setmetatable({},c)
                if self.init then
                        self.init(obj,...)
                elseif base ~= nil and base.init ~= nil then
                        base.init(obj,...)
                end
                return obj
        end
        })
        return c
end

Usage

Code:


-- class
local Animal = class()

function Animal:init()

end


-- subclass
local Dog = class(Animal)

function Dog:init()
    self.base.init(self)
end


-- create new object instance
local dog1 = Dog()


Atropos 07/06/15 10:17 AM

Thanks to those who replied, but I'm still not clear what the actual gain is from trying to force OOP like this. Can someone provide an example use case where using ZO_Object allows them to do something that would otherwise be a big pain in the ass?

Is it simply a mechanism for making programming LUA more friendly/intuitive for people who are used to other OO languages?

merlight 07/06/15 10:30 AM

Quote:

Originally Posted by Atropos (Post 21881)
Thanks to those who replied, but I'm still not clear what the actual gain is from trying to force OOP like this. Can someone provide an example use case where using ZO_Object allows them to do something that would otherwise be a big pain in the ass?

Is it simply a mechanism for making programming LUA more friendly/intuitive for people who are used to other OO languages?

Think of it as convenient syntax sugar.

Compare:
Lua Code:
  1. local Bar = {}
  2. function Bar:foo() ... end
  3.  
  4. local b = setmetatable({}, {__index = Bar})
  5. b:foo()

To:
Lua Code:
  1. local Bar = ZO_Object:Subclass()
  2. function Bar:foo() ... end
  3.  
  4. local b = Bar:New()
  5. b:foo()

It simply adds descriptive names to Lua constructs. You can see right where Bar is defined that it's a new (sub)class. And that b is an instance of Bar.

XanDDemoX 07/07/15 10:54 AM

Quote:

Originally Posted by Atropos (Post 21881)
Thanks to those who replied, but I'm still not clear what the actual gain is from trying to force OOP like this. Can someone provide an example use case where using ZO_Object allows them to do something that would otherwise be a big pain in the ass?

Is it simply a mechanism for making programming LUA more friendly/intuitive for people who are used to other OO languages?

In general functional programming vs oop can actually be a bit of a contensious topic. Theres a few comparisons of varying biases to be found on google :) Heres a reasonably neutral writeup by Robert C Martin (Uncle Bob)

http://blog.cleancoder.com/uncle-bob...24/FPvsOO.html

Personally I wouldn't want to rule either out on account of preferance. Gains of one over the other depend on suitability for the problem but also how you approach the solution. A problem could naturally lend itself to an OO solution but it still have a poor implementation and gain nothing ;)

Atropos 07/07/15 12:47 PM

Quote:

Originally Posted by XanDDemoX (Post 21895)
In general functional programming vs oop can actually be a bit of a contensious topic. Theres a few comparisons of varying biases to be found on google :)

I understand the difference between functional and OO. I was trying to encourage some discussion to quantify the advantages of using objectification in actual ESO addon applications.

For example, the following thought exercise:

Suppose you have 20 objects in a table containing data that updates several times per second. You want to render this data in a way that updates every 10th of a second (10x per second). Two ways to approach the problem might be:

Functional - Have a single OnUpdate function which loops over the elements of the table and executes some function on each element sequentially.

Object Oriented - Create each element of the table as an object that inherits its own methods and updating function. Each child object updates itself.

Is one approach more efficient (in terms of performance)? It's generally not clear to me whether there is a gain from trying to use object inheritance in LUA other than simply making it easier to think about certain types of problems.

XanDDemoX 07/07/15 08:38 PM

Quote:

Originally Posted by Atropos (Post 21899)
I understand the difference between functional and OO. I was trying to encourage some discussion to quantify the advantages of using objectification in actual ESO addon applications.

For example, the following thought exercise:

Suppose you have 20 objects in a table containing data that updates several times per second. You want to render this data in a way that updates every 10th of a second (10x per second). Two ways to approach the problem might be:

Functional - Have a single OnUpdate function which loops over the elements of the table and executes some function on each element sequentially.

Object Oriented - Create each element of the table as an object that inherits its own methods and updating function. Each child object updates itself.

Is one approach more efficient (in terms of performance)? It's generally not clear to me whether there is a gain from trying to use object inheritance in LUA other than simply making it easier to think about certain types of problems.

In my opinion the advantages and disadvantages of either approach aren't any different for ESO addons than they are for any other application.

When your talking performance you can only quantify different solutions to see which is the fastest.

I suppose something to consider is that in a class hierarchy when attempting to resolve the value of a key, each table must be searched until the value for a specific key is found.

Therefore as the height of the hierarchy grows, so will the number of tables to potentially search for the matching value of a particular key. Which of course will always be extra overhead on top of searching just a single table to resolve a function address or other value.

Sasky 07/07/15 10:17 PM

Quote:

Originally Posted by Atropos (Post 21899)
Functional - Have a single OnUpdate function which loops over the elements of the table and executes some function on each element sequentially.

Object Oriented - Create each element of the table as an object that inherits its own methods and updating function. Each child object updates itself.

Is one approach more efficient (in terms of performance)? It's generally not clear to me whether there is a gain from trying to use object inheritance in LUA other than simply making it easier to think about certain types of problems.

If you're using a homogenous list of elements to update, I'd expect the functional to be faster. But if you're looking at different types that just share an :OnUpdate interface, that gap would close and the OOP-version would be easier to maintain. It also depends how you code your object. See:
http://lua-users.org/wiki/ObjectBenchmarkTests

However, most addons don't need to update frequently enough that that's at all noticeable. So then the main thing is whether or not OOP is appropriate for the situation. Then again, if you have a list of tables/elements, you're doing some level of OOP in Lua, so formalizing it can usually help.

ZO_Object doesn't provide anything you can't do yourself. It's just a way to make things more compact if you use a lot of objects, which the base Lua code does. From that sense, it's more for the internal dev usage, and if you want to use it as well, it's right there. I've generally set metatables directly when I use objects, but that's more because I started that without looking at the source so didn't know what all ZO_Object was doing. Besides, I've used more of interface/implementation than subclasses, which really don't benefit from ZO_Object, especially if you want new() to do something.

kerb9729 07/08/15 10:19 AM

Thanks everyone for the responses. Makes more sense now.

Lodur 07/16/15 01:40 PM

I just read somewhere and can not for the life of me find the link to it... But to summarize:

LUA is not a functional, procedure, or OO language. It is designed to have the mechanisms needed to be used in any of these ways, but there is no policy on which way to go. Policy is left to the user.

Since ZOS does not give a best practice policy for functional vs procedural vs OO to my knowledge... Do what you want.

ZOS seems to have chosen the OO route for their own LUA code.

merlight 07/16/15 06:12 PM

I'm going to play the Grammar Nazi here, because everyone who used the word "functional" (except XanDDemoX and Lodur) actually meant "procedural". Functional programming is a whole different world. Read the article XanDDemoX posted if you're interested, although it doesn't relate to the previous discussion ;) And I'm not sure it will make any sense to you if you're not familiar with functional programming to begin with.

Lodur 07/16/15 07:31 PM

Quote:

Originally Posted by merlight (Post 22048)
I'm going to play the Grammar Nazi here, because everyone who used the word "functional" (except XanDDemoX and Lodur) actually meant "procedural". Functional programming is a whole different world. Read the article XanDDemoX posted if you're interested, although it doesn't relate to the previous discussion ;) And I'm not sure it will make any sense to you if you're not familiar with functional programming to begin with.

Yes. I mean Functional as in languages such as: Lisp, ML, Clojure, Racket, scala, etc..; and Procedural as in languages such as: C, Basic, Pascal, etc...; and OO as in: C++, Java, Ruby, etc..


All times are GMT -6. The time now is 07:46 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2014 - 2022 MMOUI