Classless class-oriented programming
- Posted by jmduro Oct 24, 2021
- 1103 views
In a previous article I showed a preprocessor to allow class-like programming. There are many other ways to do the job.
Here is one which could even be used with previous preprocessor.
Here is the library (classes.e):
namespace classes include std/convert.e -- INTERNAL CONSTANTS constant CLASS_NAME =1, CLASS_PROPERTY=2, CLASS_METHOD=3 constant PROPERTY_NAME=1, PROPERTY_VALUE=2 constant METHOD_NAME =1, METHOD_ROUTINE_ID=2 constant CLASS_ID =1, ENTITY_VALUES=2 -- INTERNAL VARIABLES public sequence classes = {}, entities = {} -- INTERNAL FUNCTIONS procedure error_message(sequence msg) puts(2, "Error: " & msg & "\n") abort(1) end procedure -- GLOBAL CLASS FUNCTIONS -- define a ClassName -- given the ClassName Name returns the ClassName ID public function class(sequence className) classes = append(classes, {className, {}, {}}) return length(classes) end function -- define a ClassName property public procedure addProperty(integer classID, sequence propertyName, object defaultValue) if classID > 0 then classes[classID][CLASS_PROPERTY] = append(classes[classID][CLASS_PROPERTY], {propertyName, defaultValue}) else error_message(sprintf("addProperty(%d, \"%s\", %s): no ClassName parameter\n", {classID, propertyName, to_string(defaultValue)})) end if end procedure -- define a ClassName method public procedure addMethod(integer classID, sequence methodName, integer routineId) if classID > 0 then classes[classID][CLASS_METHOD] = append(classes[classID][CLASS_METHOD], {methodName, routineId}) else error_message(sprintf("addMethod(%d, \"%s\", %d): no ClassName parameter\n", {classID, methodName, routineId})) end if end procedure -- get the class name of a class ID public function findClass(sequence name) for i = 1 to length(classes) do if equal(name, classes[i][CLASS_NAME]) then return i end if end for return 0 end function -- find property public function findProperty(integer classID, sequence property) for i = 1 to length(classes[classID][CLASS_PROPERTY]) do if equal(property, classes[classID][CLASS_PROPERTY][i][PROPERTY_NAME]) then return i end if end for return 0 end function -- find method routine_id public function findMethod(integer classID, sequence method) for i = 1 to length(classes[classID][CLASS_METHOD]) do if equal(method, classes[classID][CLASS_METHOD][i][METHOD_NAME]) then return classes[classID][CLASS_METHOD][i][METHOD_ROUTINE_ID] end if end for return 0 end function -- GLOBAL ENTITY FUNCTIONS -- create an Entity of the class ClassName public function new(integer classID) sequence class = classes[classID] sequence values = {} for i = 1 to length(class[CLASS_PROPERTY]) do values = append(values, class[CLASS_PROPERTY][i][PROPERTY_VALUE]) end for entities = append(entities, {classID, values}) return length(entities) end function -- get entity class ID public function getClassID(integer entityID) return entities[entityID][CLASS_ID] end function -- get property value public function getProperty(integer entityID, sequence property, object defaultValue=0) integer classID = entities[entityID][CLASS_ID] integer propertyID = findProperty(classID, property) if propertyID then return entities[entityID][ENTITY_VALUES][propertyID] end if return defaultValue end function -- set property value public procedure setProperty(integer entityID, sequence property, object val) integer classID = entities[entityID][CLASS_ID] integer propertyID = findProperty(classID, property) if propertyID then entities[entityID][ENTITY_VALUES][propertyID] = val end if end procedure -- call a method (function) within an Entity public function callMethod(integer entityID, sequence method, object methodParams= {}) integer classID = entities[entityID][CLASS_ID] integer methodID = findMethod(classID, method) if methodID then return call_func(methodID, {entityID, methodParams}) end if return -1 end function