I am working on a gun system that uses OOP. I was wondering if for example a pistol object can inherit from multiple classes like a tool class and firearm class
Right now i am using composition but it just looks weird saying Pistol.ToolClass:Equip() or Pistol.Firearm:Fire() instead of Pistol:Equip() or Pistol:Fire()
You can inherit from multiple classes, however I feel like you wouldn’t need multiple classes for a scenario like this; could you not have Tool as the superclass, firearm as a class and then pistol as a subclass?
Not even Java supports multiple inheritance. It’s considered bad practice in modern C++.
If you want a more component-based approach, you could use intersection types to create an ‘implementation’ system with delegates and all.
type Tool = {
Equip: (self: Tool) -> ()
}
type Firearm = {
Fire: (self: Firearm) -> ()
}
type Pistol = Tool & Firearm
local function CreatePistol(): Pistol
local self = {}
function self:Equip()
end
function self:Fire()
end
return self
end
Lua’s object-oriented programming (OOP) capabilities, facilitated by meta-tables, indeed allow for inheritance. The conventional approach involves wrapping another meta-table around an object to inherit from its indexed table.
However, the pivotal question arises: should we pursue this path? Ideally, I would advocate against it. OOP, as defined in textbooks, revolves around objects interacting to achieve desired program functionality. To maintain code abstractness and decoupling, it’s imperative to adhere to established principles. Among these, the Single Responsibility Principle (SRP) stands out. SRP, a core tenet of SOLID principles, dictates that an object should have only one responsibility. By inheriting from multiple objects, we risk violating this principle.
Instead, an alternative solution lies in employing dependency inversion. This approach entails internally defining methods within our class to avoid compromising the SRP. For instance, in the context of our objects, we can enhance code cleanliness by encapsulating functionality such as firing and equipping into separate methods within our base class. By doing so, we achieve the desired functionality while upholding design principles and preserving the essence of OOP.