Create objects dynamically according to class files in specified project folder - progress-4gl

We have a folder with many classes that inherit from the same base class. Their names are formatted like this:
firsttypesubclass_1.cls
firsttypesubclass_2.cls
firsttypesubclass_3.cls
secondtypesubclass_1.cls
secondtypesubclass_2.cls
The program should scan this class folder and create a temp-table with the class-name prefix and count (f.ex "firsttypesubclass" and count=3):
DEFINE PUBLIC TEMP-TABLE TT_AllSubClasses NO-UNDO
FIELD Name AS INT /* f.ex "firsttypesubclass" */
FIELD Name AS INT /* f.ex "firsttypesubclass" */
.
Then we need to create new instances dynamically according to the found classes in a loop like this:
DEF VAR newInstance AS CLASS myBaseClass NO-UNDO.
newInstance = DYNAMIC-NEW TT_AllSubClasses.Name + "_" + STRING(1)(123123) NO-ERROR.
Is there any convenient way to list the class names in the folder? Or is it possibly to get all classes that inherit from the baseclass? I'm thinking about using the file system for checking up the files.

You will have to reach out to the file system and list all class files in the relevant folder. If at runtime the source code is not available, you should base your code on R-code. INPUT FROM OS-DIR is your friend there.
If you are mixing procedural and class based R-code in those relevant folders, you'll also have to verify if the R-code is from a procedure or a class:
RCODE-INFO:FILE-NAME = cFileName .
IF RCODE-INFO:IS-CLASS THEN ...
OpenEdge 11.6 has more reflection features. But there is no functionality that lists all child classes of a given base class. As the ABL does not have a fixed library scheme for classes (like C#), that would probably also be difficult for Progress to implement.

Related

C++11 Creating an object of unknown class

I am developing a C++ application where I need to create X amount of classes. Let's say: class AAA, BBB and CCC. Each class corresponds to one type of object which I would need to process.
On the other hand, I have an input file of CVS type. One example of that input file looks like this one:
AAA,3432443,433434,11111,45678
AAA,8778776,786698,22222,86881
BBB,4452332,112234,34543,87734
So, I need to parse that input file, and according to the first element of the line (AAA, BBB, CCC), I need to create the corresponding object which will store the other values found in the line.
BUT, I cannot "embedded" in the application the possible classes (AAA, BBB, CCC) in order to use a chain of conditionals, like:
if (token == "AAA") then AAA aaa = new AAA (params);
Instead:
The application must remain independent of the existing classes, in such way that in the future we can add classes DDD, EEE, ... ZZZ, without modifying the module which creates the objects (in case of using conditionals, I should add, for instance: if (token == "DDD") then DDD ddd = new DDD(params). This is forbidden.
I have created a configuration file which provides the possible class types in the current execution:
AAA
BBB
CCC
...
In this way, I can loop over this class types and compare against the ones read from the first element in the input file lines. But I am stuck in the problem of how I can create an object of an unknown class. Something like this:
retrieved_type_from_input_file object = new retrieved_type_from_input_file(params);
where "retrieved_type_from_input_file" is a variable which contains the effective type of class I should create: AAA ... ZZZ
I am thinking in generic programming. Something like:
T object = new T(params);
But even though I can code this inside a class; in the implementation I need the real name of the class.
I am thinking also in the implementation of some kind of Factory pattern, creating some kind of abstract parent class ("Thing") from which everyone would be inheriting ( class AAA: public Thing). But all the models which I find, make explicit reference to the name of the class, in some place of the code, at the moment of creating the object.
Any help please?
Thanks a lot in advance!!
i am guessing, you are in need of code generator :
Step 1. Write a program that generates classes in .h, .cpp files based on your configuration file.
you can alse create/declare objects of the classes in this step
Step 2. Make use of generated classes , to build an exe file.
This is my rough idea, and looking for other possibilites from others.

Add a method to Matlab table class

I wish to add a method called nansubset to the table class. Essentially it allows you to call T(r,c) where r and c are real positive integer vectors possibly containing NaN's.
Stubbed code for nansubset.m could be:
function T = nansubset(T, r, c)
T = T(r,c);
end
I am following the instructions here, which detail how to add a new method to the cell class. Basically, in a folder on my Matlab path, I create a folder called #table, and within this folder, create a file called nansubset.m.
I am getting the following problems:
>> tmpT = table(); nansubset(tmpT, 1, 1)
Undefined function 'nansubset' for input arguments of type 'table'.
and
>> doc #table/nansubset
Your search - #table/nansubset - did not match any documents.
However:
edit nansubset
and
edit #table/nansubset
both open the method file in my editor.
Further, I followed the instructions in the above link to add the plus method to the cell class and find that it works perfectly.
Can someone please explain to me how I can add this additional method to the table class?
With the release of Matlab R2012b (version 8), the class folder behavior changed (emphasis is mine):
In MATLAB Versions 5 through 7, class folders do not shadow other class folders having the same name, but residing in later path folders. Instead, the class the combination of methods from all class folders having the same name define the class. This is no longer true.
For backward compatibility, classes defined in class folders always take precedence over functions and scripts having the same name, even those that come before them on the path.
The combination of the two bold statements explains the behavior:
cell is a built-in Matlab function that predates the new OOP rules that returns an instance of its class. And before R2012b, adding methods to a class folder called #cell added the methods to the object returned from the cell function (which isn't defined with a classdef nor a class folder); this ability was retained for compatibility with legacy user code.
table was added after R2012b, is defined via a class folder, and is Sealed. Since it is Sealed, it cannot be subclassed. And with the new rules, any #table folder without an associated classdef file will not register as a class folder nor will its methods be composed into the existing class unless it is part of the legacy system (like cell).
I can see three workarounds listed in the order I think is best:
Have a function on the Matlab path, just like the one you have, and always call the "method" using function notation instead of dot notation. If you need more "methods" group them in a folder or package (if good namespacing is desired) on the path. Since table is a value class, this option doesn't seem bad.
Create a wrapper class like the one below. It is cumbersome but automatically encapsulates the additional functions.
classdef MyTable < handle
properties
tab;
end
methods
function mytab = MyTable(varargin)
mytab.tab = table(varargin{:});
end
function tabnan = nansubset(mytab,r,c)
tabnan = mytab.tab(r,c);
end
end
end
Create a local copy of [matlabroot,'\toolbox\matlab\datatypes\#table\*'] and add the methods directly. I can't think of any huge drawbacks to this per se, but it feels weird copying internals like this.

Intersystems caché - programmatically create new class

Is it possible to write ObjectScript method, which will create new class in namespace and compile it? I mean programmatically create new class and store it. If so, can I edit this class using ObjectScript later(and recompile)?
Reason: I have class structure defined in string variable and I need to add new class to namespace according this string.
Nothing is impossible. Everything in Caché can be created programmatically. And, Classes is not a execution. There are at least two ways to do it:
simple SQL Query CREATE TABLE, will create a class.
and as you already mentioned ObjectScript Code, which can do this.
All of definition of any classes defined in other classes. Which you can find in package %Dictionary.
The class itself defined in %Dictionary.ClassDefinition. Which have some properties, for defining any parts of classes. So, this is a simple code which create some class, with one property.
set clsDef=##class(%Dictionary.ClassDefinition).%New()
set clsDef.Name="package.classname"
set clsDef.Super="%Persistent"
set propDef=##class(%Dictionary.PropertyDefinition).%New()
set propDef.Name="SomeProperty"
set propDef.Type="%String"
do clsDef.Properties.Insert(propDef)
do clsDef.%Save()
And in latest versions, there is one more way for create/change class. If you have text of class as you can see it in Studio. Then, you can load it in Caché, with class %Compiler.UDL.TextServices
Yes, it is. You likely want to make use of %Dictionary.ClassDefinition and the related %Dictionary.*Definition classes (especially %Dictionary.PropertyDefinition, %Dictionary.MethodDefinition and %Dictionary.IndexDefinition) to create and/or modify your class. Provided your string contains some reasonable representation of the data, you should be able to create the class this way.
The actual class documentation is available at http://docs.intersystems.com/cache20141/csp/documatic/%25CSP.Documatic.cls?CLASSNAME=%25Dictionary.ClassDefinition
You can then compile the class by calling $system.OBJ.Compile("YourPackage.YourClass","ck").
(Note: If your string contains the exported XML definition of the class, you could also write the XML representation to a stream and then call $system.OBJ.LoadStream() to import the XML definition. I would only recommend this if you have an exported class definition to start with.)

Limiting input to a vba class interface

I am trying to encapsulate the access of an XML configuration file within a (excel) vba custom class. A portion of the XML document is split into 4 or 5 repeated sections that are differentiated by an AreaID. MY question is: How can I limit the input of one of my class interfaces to the various AreaID's that may be read in from the XML document?
revision: what is the best way to control input into a class' interface from within the class (as it pertains to vba)? (i.e. public enum, secondary "helper" class, error handling from within the class, hard-coding...)
I wanted to follow up with #Tim's comment regarding enums and provide some further information as to why enums in the class code may be a good way to limit the input. According to Chip Pearson's site :
Enums cannot be declared within a procedure. They must be declared within the declarations part of a module, above and outside any procedure in the module. Class modules can declare Public Enum types but you cannot create a variable whose type is an Enum declared within a class module.
So as I understand this, if you declare the input on one of interfaces as a (public) enum that has been declared in the class itself, it will limit what values can go in based on that enum. Also the enum will still not be able to be used outside of the class structure.

When should I use package and when object in Scala?

What is the difference between package and object?
Packages are not run-time entities, objects are. You should use packages to organize the hierarchy of your code, and objects whenever you need something to store code or data (assuming plain classes and instances are not better, of course).
To add a bit to Daniel's answer:
From the Scala specifications:
Objects
Classes (§5.3) and objects (§5.4) are both defined in terms of templates.
A template defines the type signature, behavior and initial state of a trait or class of objects or of a single object.
It can have:
local modifiers (‘abstract’, ‘final’, ‘sealed’, ‘implicit’, ‘lazy’)
access modified (‘private’ | ‘protected’),
access qualifier (‘this’)
An object definition defines a single object of a new class (or: module) conforming to the template t.
It is roughly equivalent to the following three definitions, which together
define a class and create a single object of that class on demand:
final class m$cls extends t
private var m$instance = null
final def m = {
if (m$instance == null) m$instance = new m$cls
m$instance
}
An object can isolate a code common for other Class instances.. A specific usage:
Classes in Scala do not have static members; however, an equivalent effect can be achieved by an accompanying object definition.
Generally, a companion module of a class is an object which has the same name as the class and is defined in the same scope and compilation unit.
Conversely, the class is called the companion class of the module.
Packages
a package is part of compilation unit.
A compilation unit consists of a sequence of packagings, import clauses, and class
and object definitions, which may be preceded by a package clause.
A package is a special object which defines a set of member classes, objects and
packages.
Unlike other objects, packages may not be used as values. It is illegal to have a package with the same fully qualified name as a module or a class.
Top-level definitions outside a packaging are assumed to be injected into a special
empty package. That package cannot be named and therefore cannot be imported.
The special predefined name _root_ refers to the outermost root package which
contains all top-level packages.
So:
object organize code to be executed from a unique runtime instance.
package declare code namespace for the compilation step.