- Subject: [slang-users] SLang with objects ?
- From: Marko Mahnic <marko.mahnic@xxxxxxxx>
- Date: Mon, 16 Oct 2006 11:44:48 +0200
Are there any plans to add support for objects to SLang?
A while ago I was building a library for text forms in
jed and I implemented it in an OO fashion (structures with members
and methods).
The thing that I am missing the most is a way to add new members
to an existing structure. This way I could add some polymorphism.
I found a way to do it (with an empty extra field in the base "class")
but I don't consider this to be a solution:
typedef struct
{
a, b, % members
dothis, dothat % methods
extra % derived types can add members
} Base_Type;
private define impl_do_this(self) { print(self.a); ... }
private define impl_do_that(self) { print(self.b); ... }
% constructor for Base_Type
define New_Base_Type()
{
variable obj = @Base_Type;
obj.a = 0; obj.b = 0;
obj.dothis = &impl_do_this;
obj.dothat = &impl_do_that;
obj.extra = NULL;
return obj;
}
typedef struct
{
c, d, % extra members for derived type
op1, op2 % methods
} Struct_with_extra_members;
% constructor for Derived_Type
define New_Derived_Type()
{
variable obj = @Base_Type;
obj.extra = @Struct_with_extra_members;
obj.extra.c = 0;
...
return obj;
}
Here I can implement 1 level of derived objects. This was enough
(and not too hard to manage) for the project.
If I wanted to inherit from a derived object I would get obj.extra.extra.
A mess.
Some ideas
==========
The typedef struct construct could be extended like this
typedef struct {
c, d,
op1, op2
} Derived_Type (Base_Type)
which would produce a structure like
struct { a, b, dothis, dothat, c, d, op1, op2 }
Another not so elegant solution is something like:
define New_Derived_Type()
{
variable obj = @Base_Type;
struct_add_member(obj, "c");
struct_add_member(obj, "d");
...
return obj;
}
But maybe the best syntax would be to add a keyword like "class" or
"object":
class Derived_Type (Base_Type)
{
c, d, ...
};
For the classes to be real classes, there should be support
for virtual functions. At the moment it is possible to override
an existing function from the base class:
private define impl_special_do_this(self)
{ print("Derived " + self.a); ... }
define New_Derived_Type()
{
variable obj = @Base_Type;
% override a method from the base class
obj.dothis = &impl_special_do_this;
}
You can still call the original method from the base class:
private define impl_special_do_this(self)
{
print("Derived implementation calling Base implementation");
impl_do_this(self);
}
You have to know which is the base class and what function you
reimplemented in the derived class. You also have to have access
to the function impl_do_this.
To make the code more OO I made all impl_* functions private to
force the programmer to access them only by using object methods.
Now, when I define the derived object in anoter file I no longer
have access to impl_do_this. What I could do is:
define New_Derived_Type()
{
variable obj = @Base_Type;
...
struct_add_member(obj, "base_do_this");
...
% override a method from the base class
obj.base_do_this = obj.dothis;
obj.dothis = &impl_special_do_this;
}
private define impl_special_do_this(self)
{
print("Derived implementation calling Base implementation");
self.base_do_this();
}
This could be implemented in SLang library internally. Methods
could somehow be declared virtual. Each instance of an object
would have a poiner to its static type-descriptor (Base_Type).
(could typeof() be used?).
Type-descriptors would have a pointer (__base) to their base
type-descriptors.
define New_Base_Type()
{
variable obj = @Base_Type;
% Base_Type.__base = NULL
struct_virtual(obj.dothis, &impl_do_this);
% converted internally to: typeof(obj).dothis = &impl_do_this
}
% Base_Type.dothis points to impl_do_this
define New_Derived_Type()
{
variable obj = @Derived_Type;
% Derived_Type.__base points to Base_Type
% Derived_Type.dothis points to impl_do_this
struct_override(obj.dothis, &impl_special_do_this);
% converted internally to:
% typeof(obj).dothis = &impl_special_do_this
}
% Derived_Type.dothis points to impl_special_do_this
A call like obj.dothis() would be converted internally to
typeof(obj).dothis(obj);
In the above case it would call impl_special_do_this(obj).
A call to a base classes method could be made with a type cast:
Base_Type(obj).dothis();
This call could perform a check if obj is derived from Base_Type
(using the __base field) and then call
Base_Type.dothis(obj);
Constructors (and destructors) could be added to classes. They
could be declared for example using a standard name (like with
python):
create(); % or __init__
destroy(); % or __del__
How could it all look in SLang:
class Base
{
a = 0, b = 0,
create = &impl_base_create,
virtual dothis = &impl_do_this,
dothat = &impl_do_that
};
class Derived (Base)
{
c = 0, d = 0,
create = &impl_derived_create,
override dothis = &impl_special_do_this,
};
x = new Base(); % also calls x.create()
y = new Derived();
x.dothis();
y.dothis();
Base(y).dothis();
Marko M.
_______________________________________________
To unsubscribe, visit http://jedsoft.org/slang/mailinglists.html
[2006 date index]
[2006 thread index]
[Thread Prev] [Thread Next]
[Date Prev] [Date Next]