ID:1668639
 
Currently classes in DM can only inherit from one parent. This limits the modularity of behavior. The alternative, multiple inheritance, has been requested multiple times and deferred. This post is just a showcase of an idea for a softcoded multiple inheritance model, and maybe also to throw around some ideas about how actual multiple inheritance could be implemented in DM. Feel free to post any ideas/alterations/criticisms, it'd be most appreciated.

p.s. Sorry if this is in the wrong forum, I suppose it's more of a tutorials&snippets+design philosophy+feature request hybrid post (see wat i did there?).

Overview:
The basic idea is to add customizable alternatives to the way vars and procs are accessed that take into account a list of parents. Also, functions are added to handle the inheritance process.

Issues:
- No functionality resembling parent calls, no chain of execution control other than the 'halt' var.

[Download Demo]

// stuff for caching datums
var/cache[]
proc/cache(a,b,list/list=cache)
if(a)
if(b)
if(!list)
cache=list()
list=cache
list[a]=b
if(list&&(a in list))
return list[a]

proc/temp(type)
// all-purpose cache wrapper for datums
if(type in cache)
return cache(type)
return cache(type,new type)

// the setup
datum
var/tmp
parents[]
params[]

halt

proc
param(p)
if(p in params) return params[p]
else if(p in vars) return vars[p]

set_param(p,v)
if(!params) params = list()
if(!(p in params)) params += p
params[p]=v

inherit(datum/d)
for(var/p in params)
d.set_param(p,param(p))

func(f,...)
var
_args[] = args.Copy(2)
chain[] = parents+src
_args.Insert(1,src)
halt = null

for(var/d in chain)
if(hascall(d,f))
.=call(d,f)(arglist(_args))
if(halt) return

add_parent(p)
if(!parents) parents = list()
var/datum/d
if(ispath(p))
d = temp(p)
parents += d
d.inherit(src)

take_parent(p)
p = is_type(p)
if(p)
parents -= p
if(parents.len<1) parents=null

is_type(p)
return locate(p) in parents

New()
.=..()
for(var/p in parents)
if(ispath(p))
add_parent(p)
parents -= p

// some examples
combatant
params = list("hp" = 10)

inherit(datum/d)
.=..()
if(istype(d,/mob))
d:verbs += /combatant/proc/attack

proc
attack()
var/turf/t = get_step(src,src:dir)
for(var/atom/a in t)
if(a.is_type(/combatant))
a.func("damage",1,src)

damage(datum/ref,dmg,trg)
ref.set_param("hp",ref.param("hp")-dmg)
//oview(ref) << "[ref] is hurt by [trg] for [dmg] damage."
if(ref.param("hp") < 1)
ref.func("die",trg)

die(datum/ref,trg)
//oview(ref) << "[ref] was slain by [trg]!"

hostile
inherit(datum/d)
.=..()
if(istype(d,/atom/movable))
var/atom/movable/a = d
spawn while(a)
var/mob/m = locate(/mob) in oview(a)
if(m)
if(get_dist(m,a)>1) step_to(a,m)
else m.func("damage",1,a)
sleep(2)

item
inherit(datum/d)
.=..()
d:verbs += /item/proc/get
d:verbs += /item/proc/drop

proc
get()
set src in oview(1)
src:Move(usr)

drop()
set src in usr
src:Move(usr.loc)

tree //murderous trees
parent_type = /obj
density = 1

parents = list(/combatant,/hostile)

proc/die()
new .wood (loc)
del src

wood
parent_type = /obj
parents = list(/item)
icon = 'wood.dmi'

mob
parents = list(/combatant)
IainPeregrine wrote an article on how to use Multiple Inheritance in BYOND a while ago. Let me see if I can find the article.
Cool post! I'm not sure how that can be labelled 'multiple inheritance' though. I don't see how anything even resembling inheritance is going on. The only effect achieved could easily be replaced with the use of :, the vars var or hascall() and call().
It's interfacing, which is a different mechanism as it goes. Notionally serves the same general goal as multiple inheritance, but with different nuances.
If multiple inheritance was ever implemented, I have one way it could be implemented into the DMB file. By converting the parent_type from a string into a special list (for later versions of course in order to maintain backward compatibility with older DMB files), it could check through the list to determine if it has access to variables or procedures to each of the listed paths (though it could cause confusion if they share similar names).

Of course, I can see why multiple inheritance hasn't been implemented and I might've even read comments before. If it has to go through such checks, it could slow down games considerably due to overhead (unless it is very well optimized). It is nice to have multiple inheritance in the future though. Admittedly, I very rarely use multiple inheritance not because of lack of skill, but rather not much need at present.