How to use class inheritance?

I don’t understand classes. Looked at the animal, dog example… umm i guess im a bit dumb

I want to make a building superclass and a bunch of subclasses like farm, house, barracks, wall and town center. Heres one of my attempts to make a barracks class, but im not knowing how to design the code so that it works or call the building class methods from the barracks class

Building = class()

function Building:makeFoundation(x,y,size,player)
    
end

function Building:addHP(add1,add2) 
    -- Call this method whenever an event should change the hit points of a building
    if add2 then
        local m = get_percent(hp1,hp2)
        self.hp1 = self.hp1 + hp2 * m/100
        self.hp2 = self.hp2 + add2
    end
    if add1 then
        self.hp = self.hp + hp1
    end
end

function Building:addArmor(a1, a2) --armor types MELEE
    if a1 then
        self.armor1 = self.armor1 + a1
    end
    if a2 then
        self.armor2 = self.armor2 + a2
    end
end

function Building:select()
    -- select building
end

Barracks = class(Building)

local __size = 3.0
local __cost1 = 125
local __buildTime = 30

function Barracks:init(x,y,hp,player)
    if hp == 1 then
        self:makeFoundation(x,y,__size,player)
    else
    end
    self.hp1 = hp   --active hit points
    self.hp2 = hp   --max Hit Points
    self.player = player
    self.armor1 = 5
    self.armor2 = 10
    self.attack = nil
    self.range = nil
    self.queue = {}
end

function Barracks:addUnitToQueue()
    
end


I would recommend composition over inheritance. That is, instead of making your classes inherit, have them hold objects which perform the necessary computation and hold the data they need.

For example, have class Damageable which holds the hit points and logic to accumulate them, then class Structure which holds the foundation/building base logic, then a further class UnitQueue which handles your unit storage (I’m guessing on your design here based on your sample code above).

Barracks = class()

local __size = 3.0
local __cost1 = 125
local __buildTime = 30
local __capacity = 30

function Barracks:init(x, y, hp, player)
    self.position = vec2(x,y)
    self.structure = Structure(player, __buildTime, __cost1, __size)
    self.health = Damageable(hp)
    self.queue = UnitQueue({}, __capacity)
end

The reason I like this better than inheritance is that it prevents your base classes from becoming bloated with functionality that is too specific purely because that functionality needs to be used across more than one class.

Instead, the value of Barracks class comes from its specific configuration of reusable components, and any functionality highly specific to Barracks only.

There’s more here https://en.wikipedia.org/wiki/Composition_over_inheritance

That said, if you want to go with inheritance, you can do what you’re asking like this:

Building base class

Building = class()

function Building:init(hp)
    self.hp = hp
end

function Building:showHP()
    print("HP = ", self.hp)
end

Barracks class

Barracks = class(Building)

function Barracks:init(hp, otherData)
    -- Initialise base class
    -- this is important
    Building.init(hp)

    self.otherData = otherData
end

Using it

local barracks = Barracks(100, "Test")

barracks:showHP()

print(barracks.hp)
print(barracks.otherData)

@xThomas You’re not dumb. It takes time and experience to understand classes and inheritance. I know what inheritance is and what it’s supposed to do. I’ve never had the need to use it, so I can’t answer your questions without knowing specifics. And then I would have to write examples myself to figure out how to make it work.

@Simeon good ideas, I still have a lot to learn but I will try what you make

Related problem. I have a mesh called self.Grass02mesh in the Chunk class and I have a subclass called Tile, which takes multiple values to create a textured grass rect (addRect, setRectTex), which i then want to insert back into the aforementioned self.Grass02mesh.

Here’s my code, what I ave so far, its a bit ugly as I only started it yesterday without any real plan edit: Tile:draw() is anacharistic but I left it in there by accident, son’t want to edit code tha I already posted here, are there rules about that?


--# Main
-- 01292017.2
-- 0.1.0.3 (PRE ALPHA)

textures = {
Grass02 = readImage("Documents:Grass 02"),
Bamboo01 = readImage("Documents:Bamboo 01")
            }



Tile = class(Chunk)
tileId = 0
function Tile:init(x,y,t,i, ii)
    --Tiles are created in chunks of 8x8
    self.i = i
    self.ii = ii
    self.x = x 
    self.y = y
    self.tex = t
    local m = mesh()

    if self.tex == texture.Grass02 then
        -- Insert local mesh into parent chunk Grass02mesh
        -- Inside Chunk:init() is self.Grass02mesh, but how to edit it from the Tile class?
    elseif self.tex == texture.Bamboo01 then
        --Insert a BambooTree01 object into the parent Chunk objects table and
        -- leaves terrain into the parent chunks leaves mesh
    end
    m:addRect(x,y,64,64)
    
    local u = 1/16 * self.i - 1/16
    local v = 1/16 * self.ii - 1/16
    local w,h = 1/8,1/8
    m:setRectTex(1, u, v, w, h)
    
end
function Tile:draw()
    self.mesh:draw()
end

Chunk = class()

NumberOfChunks= 0
function Chunk:init(t)
    -- These meshes are needed to draw everything in a given chunk of the map
    self.Grass02mesh = mesh()
    self.Leavesmesh = mesh()
    self.Objectsmesh = mesh()
    self.Units = mesh()
    self.Buildings = mesh()
    self.idChunk = NumberOfChunks + 1
    local n, nn = self.idChunk*16-15, self.idChunk*16
    
    for i = n,nn do
        for ii = n,nn do
            local x = i*32
            local y = ii*32
            table.insert(gamemap,Tile(x,y,terrain.Grass02,i,ii))
        end
    end
    NumberOfChunks = NumberOfChunks + 1
end
function Chunk:draw()
    self.Grass02mesh:draw()
    self.LeavesMesh:draw()
    --later add objects, units and buildings
end

function setup()
    Chunk:init(terrain.Grass02)
end

function draw()
    Chunk:draw()
end

@xThomas At the top right of each discussion is a gear icon. If you tap that you have the option to edit your post. You can do whatever you want with your own post.

@dave1707: good to know but I was trying to ask this. How can I add stuff to things inside a class? Below you see ChunkMesh and in tile, I want to add a rectangle to ChunkMesh. Does that make sense?

Chunk = class()

function Chunk:init()
    self.ChunkMesh = mesh()
end

Tile = class(Chunk)

function Tile:init()
    Chunk.ChunkMesh:addRect(x,y,w,h)
end

@xThomas you need to call your Chunk:init function from your Tile:init like so:

function Tile:init(x,y,t,i, ii)
    -- Call super class initializer
    Chunk.init(self, t)

    --Tiles are created in chunks of 8x8
    -- ... your existing code
end

(See my Barracks / Building example above. It does this too.)

Then you can access Grass02mesh in Tile just by writing self.Grass02mesh