Hi,
I am trying to build a Interface like structure and facing some problems. Here is what I have so far:
type
ITest = tuple[self:ref TObject,
addxImpl: proc(self: ref TObject, v: Int),
getxImpl: proc(self: ref TObject): string]
TFoo = object of TObject
data: Int
TBar = object
data: string
proc addx(self: ref TFoo, v: Int) =
self.data += v
proc getx_TFoo(self: ref TFoo): string =
return $self.data
proc getIntf(self: ref TFoo): ITest =
return cast[ITest]((self, addx, getx_TFoo))
proc newTBar(): ref TBar =
new(result)
result.data = "test"
proc addx_TBar(self: ref TBar, v: Int) =
self.data &= $v
proc getx_TBar(self: ref TBar): string =
return self.data
proc getIntf(self: ref TBar): ITest =
return cast[ITest]((self, addx_TBar, getx_TBar))
proc addx(self: ITest, v: Int) {.inline.} =
self.addxImpl(self.self, v)
proc getx(self: ITest): string {.inline.} =
return self.getxImpl(self.self)
var foo: ref TFoo
new(foo)
var test: ITest = foo.getIntf()
test.addx(1)
echo test.getx()
var bar = newTBar()
test = bar.getIntf()
test.addx(1)
echo test.getx()
proc addx(self: ref TObject, v: Int) =
# note: use the same signature
var s = PFoo(self) # ugh, needs a PFoo type definition
s.data += v
I want to use Interfaces where there is no real object hierarchy, so an abstract base classes would break this idea.
closures would make this far more elegant and a self sharing pragma would be perfect. But currently I don't care to much about memory for this use-case. When memory efficiency is a problem a structure like this, would be even better:
type
ITestProcs = tuple[
addxImpl: proc(self: ref TObject, v: Int),
getxImpl: proc(self: ref TObject): string]
ITest = tuple[self:ref TObject, tab: ref ITestProcs]
If there were not the problem with name ambiguity of the implementing procs, one could write a macro which generates the getIntf proc for a given object type and a interface tuple type