Add a variable to a class instance at runtime: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Kotlin}}: Updated example see https://github.com/dkandalov/rosettacode-kotlin for details)
m (→‎{{header|Wren}}: Changed to Wren S/H)
(40 intermediate revisions by 22 users not shown)
Line 1: Line 1:
{{task|Object oriented}}
{{task|Object oriented}}

{{omit from|Rust}}
Demonstrate how to dynamically add variables to an object (a class instance) at runtime.
Demonstrate how to dynamically add variables to an object (a class instance) at runtime.


Line 7: Line 7:
=={{header|ActionScript}}==
=={{header|ActionScript}}==
In ActionScript this can be done using an Object object
In ActionScript this can be done using an Object object
<lang actionscript>var object:Object = new Object();
<syntaxhighlight lang="actionscript">var object:Object = new Object();
object.foo = "bar";</lang>
object.foo = "bar";</syntaxhighlight>
Or by creating a dynamic class
Or by creating a dynamic class
<lang actionscript>package
<syntaxhighlight lang="actionscript">package
{
{
public dynamic class Foo
public dynamic class Foo
Line 16: Line 16:
// ...
// ...
}
}
}</lang>
}</syntaxhighlight>
<lang actionscript>var foo:Foo = new Foo();
<syntaxhighlight lang="actionscript">var foo:Foo = new Foo();
foo.bar = "zap";</lang>
foo.bar = "zap";</syntaxhighlight>
{{omit from|Modula-2}}
{{omit from|Scheme}}


=={{header|Ada}}==
=={{header|Ada}}==
Ada is not a dynamically typed language. Yet it supports mix-in inheritance, run-time inheritance and interfaces. These three allow us to achieve the desired effect, however questionably useful it could be. The example declares an interface of the class (Class). Then a concrete type is created (Base). The object E is an instance of Base. Later, at the run time, a new type Monkey_Patch is created such that it refers to E and implements the class interface per delegation to E. Monkey_Patch has a new integer member Foo and EE is an instance of Monkey_Path. For the user EE appears as E with Foo.
Ada is not a dynamically typed language. Yet it supports mix-in inheritance, run-time inheritance and interfaces. These three allow us to achieve the desired effect, however questionably useful it could be. The example declares an interface of the class (Class). Then a concrete type is created (Base). The object E is an instance of Base. Later, at the run time, a new type Monkey_Patch is created such that it refers to E and implements the class interface per delegation to E. Monkey_Patch has a new integer member Foo and EE is an instance of Monkey_Path. For the user EE appears as E with Foo.
<lang ada>with Ada.Text_IO; use Ada.Text_IO;
<syntaxhighlight lang="ada">with Ada.Text_IO; use Ada.Text_IO;


procedure Dynamic is
procedure Dynamic is
Line 63: Line 61:
Put_Line (EE.Boo & " with" & Integer'Image (EE.Foo));
Put_Line (EE.Boo & " with" & Integer'Image (EE.Foo));
end;
end;
end Dynamic;</lang>
end Dynamic;</syntaxhighlight>
Sample output:
Sample output:
<pre>
<pre>
I am Class with 1
I am Class with 1
</pre>
</pre>

=={{header|Arturo}}==

<syntaxhighlight lang="rebol">define :myClass [name,surname][]

myInstance: to :myClass ["John" "Doe"]
print myInstance

myInstance\age: 35
print myInstance</syntaxhighlight>

{{out}}

<pre>[name:John surname:Doe]
[name:John surname:Doe age:35]</pre>

=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
{{works with|AutoHotkey_L}}
{{works with|AutoHotkey_L}}
<lang AutoHotkey>e := {}
<syntaxhighlight lang="autohotkey">e := {}
e.foo := 1 </lang>
e.foo := 1 </syntaxhighlight>


=={{header|BBC BASIC}}==
=={{header|BBC BASIC}}==
{{works with|BBC BASIC for Windows}}
{{works with|BBC BASIC for Windows}}
It's not really intended that you should do this, but if you must you can:
It's not really intended that you should do this, but if you must you can:
<lang bbcbasic> INSTALL @lib$+"CLASSLIB"
<syntaxhighlight lang="bbcbasic"> INSTALL @lib$+"CLASSLIB"
REM Create a base class with no members:
REM Create a base class with no members:
Line 106: Line 120:
IF EVAL("FNassign(" + v$ + "," + n$ + ")")
IF EVAL("FNassign(" + v$ + "," + n$ + ")")
ENDPROC
ENDPROC
DEF FNassign(RETURN n, v) : n = v : = 0</lang>
DEF FNassign(RETURN n, v) : n = v : = 0</syntaxhighlight>


=={{header|Bracmat}}==
=={{header|Bracmat}}==
This solution saves the original members and methods in a variable, using pattern matching. Then, using macro expansion, a new object is created with an additional member variable and also an additional method. Because the new object is assigned to the same variable as the original object, the original object ceases to exist.
This solution saves the original members and methods in a variable, using pattern matching. Then, using macro expansion, a new object is created with an additional member variable and also an additional method. Because the new object is assigned to the same variable as the original object, the original object ceases to exist.
<lang bracmat>( ( struktuur
<syntaxhighlight lang="bracmat">( ( struktuur
= (aMember=) (aMethod=.!(its.aMember))
= (aMember=) (aMethod=.!(its.aMember))
)
)
Line 135: Line 149:
& out$("aMember contains:" (object..aMethod)$)
& out$("aMember contains:" (object..aMethod)$)
& out$("anotherMember contains:" (object..anotherMethod)$)
& out$("anotherMember contains:" (object..anotherMethod)$)
&);</lang>
&);</syntaxhighlight>
Output:
Output:
<lang bracmat>Object as originally created:
<syntaxhighlight lang="bracmat">Object as originally created:
(object=
(object=
=(aMember=) (aMethod=.!(its.aMember)));
=(aMember=) (aMethod=.!(its.aMember)));
Line 151: Line 165:
Call both methods and output their return values.
Call both methods and output their return values.
aMember contains: A value
aMember contains: A value
anotherMember contains: some other value</lang>
anotherMember contains: some other value</syntaxhighlight>


=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
{{works with|C sharp|C#|4.0}}
{{works with|C sharp|C#|4.0}}
<lang csharp>// ----------------------------------------------------------------------------------------------
<syntaxhighlight lang="csharp">// ----------------------------------------------------------------------------------------------
//
//
// Program.cs - DynamicClassVariable
// Program.cs - DynamicClassVariable
Line 191: Line 205:
#endregion
#endregion
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
<pre>sampleObj.bar = 1
<pre>sampleObj.bar = 1
< Press any key ></pre>
< Press any key ></pre>



=={{header|CoffeeScript}}==
=={{header|CoffeeScript}}==
<lang coffeescript># CoffeeScript is dynamic, just like the Javascript it compiles to.
<syntaxhighlight lang="coffeescript"># CoffeeScript is dynamic, just like the Javascript it compiles to.
# You can dynamically add attributes to objects.
# You can dynamically add attributes to objects.


Line 217: Line 230:
e.yo = -> "baz"
e.yo = -> "baz"
console.log e.foo, e.yo()
console.log e.foo, e.yo()
</syntaxhighlight>
</lang>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
Line 225: Line 238:
{{libheader|Closer to MOP}}
{{libheader|Closer to MOP}}


<lang lisp>(defun augment-instance-with-slots (instance slots)
<syntaxhighlight lang="lisp">(defun augment-instance-with-slots (instance slots)
(change-class instance
(change-class instance
(make-instance 'standard-class
(make-instance 'standard-class
:direct-superclasses (list (class-of instance))
:direct-superclasses (list (class-of instance))
:direct-slots slots)))</lang>
:direct-slots slots)))</syntaxhighlight>


Example:
Example:


<lang lisp>CL-USER> (let* ((instance (make-instance 'foo :bar 42 :baz 69))
<syntaxhighlight lang="lisp">CL-USER> (let* ((instance (make-instance 'foo :bar 42 :baz 69))
(new-slots '((:name xenu :initargs (:xenu)))))
(new-slots '((:name xenu :initargs (:xenu)))))
(augment-instance-with-slots instance new-slots)
(augment-instance-with-slots instance new-slots)
Line 244: Line 257:
BAR = 42
BAR = 42
BAZ = 69
BAZ = 69
XENU = 666</lang>
XENU = 666</syntaxhighlight>


The following REPL transcript (from [[LispWorks]]) shows the definition of a class <code>some-class</code> with no slots, and the creation of an instance of the class. The first attempt to access the slot named <code>slot1</code> signals an error as there is no such slot. Then the class is redefined to have such a slot, and with a default value of 23. Attempting to access the slot in the preëxisting instance now gives the default value, since the slot has been added to the instance. This behavior is specified in [http://www.lispworks.com/documentation/HyperSpec/Body/04_cf.htm §4.3.6 Redefining Classes] of the [http://www.lispworks.com/documentation/HyperSpec/Front/index.htm HyperSpec].
The following REPL transcript (from [[LispWorks]]) shows the definition of a class <code>some-class</code> with no slots, and the creation of an instance of the class. The first attempt to access the slot named <code>slot1</code> signals an error as there is no such slot. Then the class is redefined to have such a slot, and with a default value of 23. Attempting to access the slot in the preëxisting instance now gives the default value, since the slot has been added to the instance. This behavior is specified in [http://www.lispworks.com/documentation/HyperSpec/Body/04_cf.htm §4.3.6 Redefining Classes] of the [http://www.lispworks.com/documentation/HyperSpec/Front/index.htm HyperSpec].
Line 273: Line 286:


=={{header|D}}==
=={{header|D}}==
<lang d>struct Dynamic(T) {
<syntaxhighlight lang="d">struct Dynamic(T) {
private T[string] vars;
private T[string] vars;


Line 303: Line 316:
writeln(d2.a, " ", d2.b, " ", d2.c);
writeln(d2.a, " ", d2.b, " ", d2.c);
immutable int x = d2.b.get!int;
immutable int x = d2.b.get!int;
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>10.5 20.2
<pre>10.5 20.2
Hello 11 ['x':2, 'y':4]</pre>
Hello 11 ['x':2, 'y':4]</pre>
If you want Dynamic to be a class the code is similar. If the attribute names aren't known at compile-time, you have to use a more normal syntax:
If you want Dynamic to be a class the code is similar. If the attribute names aren't known at compile-time, you have to use a more normal syntax:
<lang d>import std.stdio, std.variant, std.conv;
<syntaxhighlight lang="d">import std.stdio, std.variant, std.conv;


struct Dyn {
struct Dyn {
Line 320: Line 333:
d[attribute_name] = "something";
d[attribute_name] = "something";
writeln(d[attribute_name]);
writeln(d[attribute_name]);
}</lang>
}</syntaxhighlight>
{{out}}
{{out}}
<pre>something</pre>
<pre>something</pre>
Line 327: Line 340:
ELENA does not support adding a field at run-time but it can be simulated with the help of a mix-in.
ELENA does not support adding a field at run-time but it can be simulated with the help of a mix-in.


ELENA 3.2:
ELENA 6.x:
<lang elena>import extensions.
<syntaxhighlight lang="elena">import extensions;


class Extender :: BaseExtender
class Extender : BaseExtender
{
{
object prop foo :: theField.
object foo : prop;
constructor new : anObject
constructor(object)
[
{
theObject := anObject.
this object := object
]
}
}
}


public program()
program =
{
[
var anObject := 234.
var object := 234;
// extending an object with a field
// extending an object with a field
anObject := Extender new(anObject).
object := new Extender(object);


anObject foo := "bar".
object.foo := "bar";


console printLine(anObject,".foo=",anObject foo).
console.printLine(object,".foo=",object.foo);


console readChar.
console.readChar()
}</syntaxhighlight>
].</lang>
{{out}}
{{out}}
<pre>
<pre>
Line 363: Line 376:
'''Array:'''
'''Array:'''
In this example we add a function (which prints out the content of the array) and a new value. While we are not technically adding a "variable", this example is presented to show similar type of functionality.
In this example we add a function (which prints out the content of the array) and a new value. While we are not technically adding a "variable", this example is presented to show similar type of functionality.
<lang falcon>vect = [ 'alpha', 'beta', 'gamma' ]
<syntaxhighlight lang="falcon">vect = [ 'alpha', 'beta', 'gamma' ]
vect.dump = function ()
vect.dump = function ()
for n in [0: self.len()]
for n in [0: self.len()]
Line 370: Line 383:
end
end
vect += 'delta'
vect += 'delta'
vect.dump()</lang>
vect.dump()</syntaxhighlight>
Output from the above:
Output from the above:
<lang falcon>0: alpha
<syntaxhighlight lang="falcon">0: alpha
1: beta
1: beta
2: gamma
2: gamma
3: delta</lang>
3: delta</syntaxhighlight>
'''Dictionary:'''
'''Dictionary:'''
In this example we will add a variable through the use of an object from a bless'ed dictionary. We create a new variable called 'newVar' at runtime and assign a string to it. Additionally we assign an external, to the object, function (sub_func) to the variable 'sub'.
In this example we will add a variable through the use of an object from a bless'ed dictionary. We create a new variable called 'newVar' at runtime and assign a string to it. Additionally we assign an external, to the object, function (sub_func) to the variable 'sub'.
<lang falcon>function sub_func( value )
<syntaxhighlight lang="falcon">function sub_func( value )
self['prop'] -= value
self['prop'] -= value
return self.prop
return self.prop
Line 392: Line 405:
])
])


dict[ 'newVar' ] = "I'm Rich In Data"</lang>
dict[ 'newVar' ] = "I'm Rich In Data"</syntaxhighlight>


=={{header|FBSL}}==
=={{header|FBSL}}==
FBSL class instances aren't expandable with additional, directly accessible public methods at runtime once the class template is defined in the user code. But FBSL has an extremely powerful feature -- an ExecLine() function -- which permits the user to execute any additional code on the fly either privately (bypassing the main code flow) or publicly (interacting with the main code). ExecLine() can be used for a variety of applications from the fine-tuning of current tasks to designing application plug-ins or completely standalone code debuggers. The following class instance may be stuffed up at runtime with any code from simple variables to executable private methods and properties.
FBSL class instances aren't expandable with additional, directly accessible public methods at runtime once the class template is defined in the user code. But FBSL has an extremely powerful feature -- an ExecLine() function -- which permits the user to execute any additional code on the fly either privately (bypassing the main code flow) or publicly (interacting with the main code). ExecLine() can be used for a variety of applications from the fine-tuning of current tasks to designing application plug-ins or completely standalone code debuggers. The following class instance may be stuffed up at runtime with any code from simple variables to executable private methods and properties.
<lang qbasic>#APPTYPE CONSOLE
<syntaxhighlight lang="qbasic">#APPTYPE CONSOLE


CLASS Growable
CLASS Growable
Line 426: Line 439:
PRINT Sponge.Yield()
PRINT Sponge.Yield()


PAUSE</lang>
PAUSE</syntaxhighlight>
'''Output:'''
'''Output:'''
1234567890
1234567890
Line 438: Line 451:
Needs the FMS-SI (single inheritance) library code located here:
Needs the FMS-SI (single inheritance) library code located here:
http://soton.mpeforth.com/flag/fms/index.html
http://soton.mpeforth.com/flag/fms/index.html
<lang forth>include FMS-SI.f
<syntaxhighlight lang="forth">include FMS-SI.f
include FMS-SILib.f
include FMS-SILib.f


Line 468: Line 481:


main \ => Now is the time 3.14159
main \ => Now is the time 3.14159
</syntaxhighlight>
</lang>


=={{header|FreeBASIC}}==
<syntaxhighlight lang="freebasic">
' Class ... End Class
' Esta característica aún no está implementada en el compilador.
</syntaxhighlight>


=={{header|Go}}==
{{trans|Kotlin}}
<br>
Firstly, Go doesn't have classes or class variables but does have structs (an analogous concept) which consist of fields.

Adding fields to a struct at runtime is not possible as Go is a statically typed, compiled language and therefore the names of all struct fields need to be known at compile time.

However, as in the case of Groovy and Kotlin, we can ''make it appear'' as though fields are being added at runtime by using the built-in map type. For example:
<syntaxhighlight lang="go">package main

import (
"bufio"
"fmt"
"log"
"os"
)

type SomeStruct struct {
runtimeFields map[string]string
}

func check(err error) {
if err != nil {
log.Fatal(err)
}
}

func main() {
ss := SomeStruct{make(map[string]string)}
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("Create two fields at runtime: ")
for i := 1; i <= 2; i++ {
fmt.Printf(" Field #%d:\n", i)
fmt.Print(" Enter name : ")
scanner.Scan()
name := scanner.Text()
fmt.Print(" Enter value : ")
scanner.Scan()
value := scanner.Text()
check(scanner.Err())
ss.runtimeFields[name] = value
fmt.Println()
}
for {
fmt.Print("Which field do you want to inspect ? ")
scanner.Scan()
name := scanner.Text()
check(scanner.Err())
value, ok := ss.runtimeFields[name]
if !ok {
fmt.Println("There is no field of that name, try again")
} else {
fmt.Printf("Its value is '%s'\n", value)
return
}
}
}</syntaxhighlight>

{{out}}
Sample input/output:
<pre>
Create two fields at runtime:
Field #1:
Enter name : a
Enter value : rosetta

Field #2:
Enter name : b
Enter value : 64

Which field do you want to inspect ? a
Its value is 'rosetta'
</pre>


=={{header|Groovy}}==
=={{header|Groovy}}==


Any [[Groovy]] class that implements "''Object get(String)''" and "''void set(String, Object)''" will have the '''apparent''' capability to add new properties. However, this capability will only work as expected with an appropriate implementation, backed by a Map object or something very much like a Map.
Any [[Groovy]] class that implements "''Object get(String)''" and "''void set(String, Object)''" will have the '''apparent''' capability to add new properties. However, this capability will only work as expected with an appropriate implementation, backed by a Map object or something very much like a Map.
<lang groovy>class A {
<syntaxhighlight lang="groovy">class A {
final x = { it + 25 }
final x = { it + 25 }
private map = new HashMap()
private map = new HashMap()
Object get(String key) { map[key] }
Object get(String key) { map[key] }
void set(String key, Object value) { map[key] = value }
void set(String key, Object value) { map[key] = value }
}</lang>
}</syntaxhighlight>


Test:
Test:
<lang groovy>def a = new A()
<syntaxhighlight lang="groovy">def a = new A()
a.y = 55
a.y = 55
a.z = { println (new Date()); Thread.sleep 5000 }
a.z = { println (new Date()); Thread.sleep 5000 }
Line 489: Line 584:
(0..2).each(a.z)
(0..2).each(a.z)


println a.q</lang>
println a.q</syntaxhighlight>


Output:
Output:
Line 498: Line 593:
Wed Feb 23 21:33:50 CST 2011
Wed Feb 23 21:33:50 CST 2011
null</pre>
null</pre>

=={{header|Io}}==

All "instance variables" (or slots in Io nomenclature) are created at runtime.

<lang io>Empty := Object clone

e := Empty clone
e foo := 1</lang>


=={{header|Icon}} and {{header|Unicon}}==
=={{header|Icon}} and {{header|Unicon}}==
{{omit from|Icon}}
Unicon implements object environments with records and supporting procedures for creation, initialization, and methods. To modify an instance you must create a new record then copy, amend, and replace it. Strictly speaking we can't guarantee the replace as there is no way to modify the existing object and we are creating a new instance with extensions. The procedures ''constructor'' and ''fieldnames'' are needed. This example doesn't do error checking. Here ''extend'' takes three arguments, the class instance, a list of new variable names as strings, and an optional list of new values to be assigned. The new instance is returned and the object is replaced by assignment. The caveat here is that if the object was assigned to anything else we will now have two objects floating around with possible side effects. As written this isn't safe from name collisions - aside from local declarations the use of a fixed constructor name uses the global name space. There is a final caveat that needs to be observed - if future implementations of objects change then this could easily stop working.
Unicon implements object environments with records and supporting procedures for creation, initialization, and methods. To modify an instance you must create a new record then copy, amend, and replace it. Strictly speaking we can't guarantee the replace as there is no way to modify the existing object and we are creating a new instance with extensions. The procedures ''constructor'' and ''fieldnames'' are needed. This example doesn't do error checking. Here ''extend'' takes three arguments, the class instance, a list of new variable names as strings, and an optional list of new values to be assigned. The new instance is returned and the object is replaced by assignment. The caveat here is that if the object was assigned to anything else we will now have two objects floating around with possible side effects. As written this isn't safe from name collisions - aside from local declarations the use of a fixed constructor name uses the global name space. There is a final caveat that needs to be observed - if future implementations of objects change then this could easily stop working.


''Note:'' Unicon can be translated via a command line switch into icon which allows for classes to be shared with Icon code (assuming no other incompatibilities exist).
''Note:'' Unicon can be translated via a command line switch into icon which allows for classes to be shared with Icon code (assuming no other incompatibilities exist).
<lang unicon>
<syntaxhighlight lang="unicon">
link ximage
link ximage


Line 540: Line 625:
x[newvars[i]] := newvals[i] # add new vars = values
x[newvars[i]] := newvals[i] # add new vars = values
return x
return x
end</lang>
end</syntaxhighlight>


{{libheader|Icon Programming Library}}
{{libheader|Icon Programming Library}}
Line 566: Line 651:
R_tempconstructor_1.d := 9
R_tempconstructor_1.d := 9
R_tempconstructor_1.e := 7</pre>
R_tempconstructor_1.e := 7</pre>

=={{header|Io}}==

All "instance variables" (or slots in Io nomenclature) are created at runtime.

<syntaxhighlight lang="io">Empty := Object clone

e := Empty clone
e foo := 1</syntaxhighlight>


=={{header|J}}==
=={{header|J}}==
If you assign a value to the name which references a property of a class instance, that name within that instance gets that value.
If you assign a value to the name which references a property of a class instance, that name within that instance gets that value.


<lang j> C=:<'exampleclass' NB. this will be our class name
<syntaxhighlight lang="j"> C=:<'exampleclass' NB. this will be our class name
V__C=: 0 NB. ensure the class exists
V__C=: 0 NB. ensure the class exists
OBJ1=:conew 'exampleclass' NB. create an instance of our class
OBJ1=:conew 'exampleclass' NB. create an instance of our class
Line 582: Line 676:
0
0
W__OBJ2 NB. our other instance does not
W__OBJ2 NB. our other instance does not
|value error</lang>
|value error</syntaxhighlight>

=={{header|Java}}==
Adding variables to an object at runtime is not possible in Java which is a statically typed language requiring the names of all class variables to be known at compile time.

However, we can make it appear as though variables are being added at runtime by using a Map or similar structure.
<syntaxhighlight lang="java">
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public final class AddVariableToClassInstanceAtRuntime {

public static void main(String[] args) {
Demonstration demo = new Demonstration();
System.out.println("Create two variables at runtime: ");
Scanner scanner = new Scanner(System.in);
for ( int i = 1; i <= 2; i++ ) {
System.out.println(" Variable number " + i + ":");
System.out.print(" Enter name: ");
String name = scanner.nextLine();
System.out.print(" Enter value: ");
String value = scanner.nextLine();
demo.runtimeVariables.put(name, value);
System.out.println();
}
scanner.close();
System.out.println("Two new runtime variables appear to have been created.");
for ( Map.Entry<String, Object> entry : demo.runtimeVariables.entrySet() ) {
System.out.println("Variable " + entry.getKey() + " = " + entry.getValue());
}
}

}

final class Demonstration {
Map<String, Object> runtimeVariables = new HashMap<String, Object>();
}
</syntaxhighlight>
{{ out }}
<pre>
Create two variables at runtime:
Variable number 1:
Enter name: Test
Enter value: 42

Variable number 2:
Enter name: Item
Enter value: 3.14

Two new runtime variables appear to have been created.
Variable Item = 3.14
Variable Test = 42
</pre>


=={{header|JavaScript}}==
=={{header|JavaScript}}==
This kind of thing is fundamental to JavaScript, as it's a prototype-based language rather than a class-based one.
This kind of thing is fundamental to JavaScript, as it's a prototype-based language rather than a class-based one.
<lang javascript>e = {} // generic object
<syntaxhighlight lang="javascript">e = {} // generic object
e.foo = 1
e.foo = 1
e["bar"] = 2 // name specified at runtime</lang>
e["bar"] = 2 // name specified at runtime</syntaxhighlight>

=={{header|jq}}==
jq's "+" operator can be used to add a key/value pair (or to add multiple key-value pairs) to an existing object at runtime, but
jq is a functional programming language, and objects themselves cannot be altered. Thus it may be helpful to introduce a variable, since the value of a variable can in effect be updated. For example:
<syntaxhighlight lang="jq">{"a":1} as $a | ($a + {"b":2}) as $a | $a
</syntaxhighlight>Thus the value of $a has undergone the desired transition, that is, its final value is {"a":1, "b":2}.

A Javascript-like syntax can also be used to add (or update) a key, for example:<syntaxhighlight lang="jq">$a|.c = 3
# or equivalently:
$a|.["c"] = 3</syntaxhighlight>

=={{header|Julia}}==
Julia does not allow direct modification of the data member variables of a type,
though class methods (just Julia functions) can be added without difficulty.
For special situations, such as when parsing an input file, where new data type names
may be appropriate, this can be accommodated using a Dict as one of the class variables.
For example, consider the below JSON input data for a program processing phone numbers,
where the type of phone numbers for the person is unknown until run-time:
<syntaxhighlight lang="xml">
{"phoneNumbers": [
{
"type": "home",
"number": "212 555-1234"
},
{
"type": "office",
"number": "646 555-4567"
},
{
"type": "mobile",
"number": "123 456-7890"
}]}
</syntaxhighlight>
Add the data into a class member that is declared as a Dict structure:
<syntaxhighlight lang="julia">
mutable struct Contact
name::String
phonenumber::Dict{Any,Any}
end

person = Contact("Jane Doe", Dict())
person.phonenumber["home"] = "212 555-1234"
</syntaxhighlight>


=={{header|Kotlin}}==
=={{header|Kotlin}}==
Line 595: Line 788:
However, as in the case of Groovy, we can ''make it appear'' as though variables are being added at runtime by using a Map or similar structure. For example:
However, as in the case of Groovy, we can ''make it appear'' as though variables are being added at runtime by using a Map or similar structure. For example:


<lang scala>// version 1.1.2
<syntaxhighlight lang="scala">// version 1.1.2


class SomeClass {
class SomeClass {
Line 624: Line 817:
}
}
}
}
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 642: Line 835:
</pre>
</pre>


=={{header|jq}}==
=={{header|Latitude}}==
jq's "+" operator can be used to add a key/value pair (or to add multiple key-value pairs) to an existing object at runtime, but
jq is a functional programming language, and objects themselves cannot be altered. Thus it may be helpful to introduce a variable, since the value of a variable can in effect be updated. For example:
<lang jq>{"a":1} as $a | ($a + {"b":2}) as $a | $a
</lang>Thus the value of $a has undergone the desired transition, that is, its final value is {"a":1, "b":2}.


Latitude is prototype-oriented, so adding slots at runtime is very straightforward and common.
A Javascript-like syntax can also be used to add (or update) a key, for example:<lang jq>$a|.c = 3
<syntaxhighlight lang="latitude">myObject := Object clone.
# or equivalently:
$a|.["c"] = 3</lang>


;; Name known at compile-time.
=={{header|LOLCODE}}==
myObject foo := "bar".
<tt>BUKKIT</tt>s (the all-purpose container type) can be added to at any point during execution, and the <tt>SRS</tt> operator permits the creation of identifiers from strings. This program and its output demonstrate both by prompting the user for a name and a value, modifying the object accordingly, and then printing the value of the new variable.
<lang LOLCODE>HAI 1.3


;; Name known at runtime.
I HAS A object ITZ A BUKKIT
myObject slot 'foo = "bar".</syntaxhighlight>
I HAS A name, I HAS A value


=={{header|Lingo}}==
IM IN YR interface
<syntaxhighlight lang="lingo">obj = script("MyClass").new()
VISIBLE "R U WANTIN 2 (A)DD A VAR OR (P)RINT 1? "!
I HAS A option, GIMMEH option


put obj.foo
option, WTF?
OMG "A"
-- "FOO"
VISIBLE "NAME: "!, GIMMEH name
VISIBLE "VALUE: "!, GIMMEH value
object HAS A SRS name ITZ value, GTFO
OMG "P"
VISIBLE "NAME: "!, GIMMEH name
VISIBLE object'Z SRS name
OIC
IM OUTTA YR interface

KTHXBYE</lang>
Example run:
<pre>R U WANTIN 2 (A)DD A VAR OR (P)RINT 1? A
NAME: foo
VALUE: 42
R U WANTIN 2 (A)DD A VAR OR (P)RINT 1? P
NAME: foo
42</pre>


-- add new property 'bar'
obj.setProp(#bar, "BAR")
put obj.bar
-- "BAR"</syntaxhighlight>


=={{header|Logtalk}}==
=={{header|Logtalk}}==
Line 689: Line 862:
The following example uses a prototype for simplicity.
The following example uses a prototype for simplicity.


<lang logtalk>
<syntaxhighlight lang="logtalk">
% we start by defining an empty object
% we start by defining an empty object
:- object(foo).
:- object(foo).
Line 708: Line 881:


:- end_category.
:- end_category.
</syntaxhighlight>
</lang>


We can test our example by compiling and loading the two entities above and then querying the object:
We can test our example by compiling and loading the two entities above and then querying the object:


<lang logtalk>
<syntaxhighlight lang="logtalk">
| ?- foo::bar(X).
| ?- foo::bar(X).
X = 1 ;
X = 1 ;
Line 718: Line 891:
X = 3
X = 3
true
true
</syntaxhighlight>
</lang>

=={{header|LOLCODE}}==
<tt>BUKKIT</tt>s (the all-purpose container type) can be added to at any point during execution, and the <tt>SRS</tt> operator permits the creation of identifiers from strings. This program and its output demonstrate both by prompting the user for a name and a value, modifying the object accordingly, and then printing the value of the new variable.
<syntaxhighlight lang="lolcode">HAI 1.3

I HAS A object ITZ A BUKKIT
I HAS A name, I HAS A value

IM IN YR interface
VISIBLE "R U WANTIN 2 (A)DD A VAR OR (P)RINT 1? "!
I HAS A option, GIMMEH option

option, WTF?
OMG "A"
VISIBLE "NAME: "!, GIMMEH name
VISIBLE "VALUE: "!, GIMMEH value
object HAS A SRS name ITZ value, GTFO
OMG "P"
VISIBLE "NAME: "!, GIMMEH name
VISIBLE object'Z SRS name
OIC
IM OUTTA YR interface

KTHXBYE</syntaxhighlight>
Example run:
<pre>R U WANTIN 2 (A)DD A VAR OR (P)RINT 1? A
NAME: foo
VALUE: 42
R U WANTIN 2 (A)DD A VAR OR (P)RINT 1? P
NAME: foo
42</pre>


=={{header|Lua}}==
=={{header|Lua}}==
<lang lua>empty = {}
<syntaxhighlight lang="lua">empty = {}
empty.foo = 1</lang>
empty.foo = 1</syntaxhighlight>

=={{header|M2000 Interpreter}}==
Adding y member to an object with a x member which made by a class alfa (a global function). We can make m as a copy of this new group (which is in a container, in a(3)). We can make a pointer to A(3) and handle the new member.

<syntaxhighlight lang="m2000 interpreter">
Module checkit {
class alfa {
x=5
}
\\ a class is a global function which return a group
Dim a(5)=alfa()
Print a(3).x=5
For a(3) {
group anyname { y=10}
\\ merge anyname to this (a(3))
this=anyname
}
Print a(3).y=10
Print Valid(a(2).y)=false
\\ make a copy of a(3) to m
m=a(3)
m.y*=2
Print m.y=20, a(3).y=10
\\ make a pointer to a(3) in n
n->a(3)
Print n=>y=10
n=>y+=20
Print a(3).y=30
\\ now n points to a(2)
n->a(2)
Print Valid(n=>y)=false ' y not exist in a(2)
Print n is a(2) ' true
\\ we don't have types for groups
Print valid(@n as m)=false ' n haven't all members of m
Print valid(@m as n)=true ' m have all members of n
}
checkit
</syntaxhighlight>


=={{header|Mathematica}}==
=={{header|Mathematica}}/{{header|Wolfram Language}}==
Mathematica doesn't rally have classes, so it doesn't have class variables. However, many rules can be applied to a single tag, so it has some aspects similar to a class. With that definition, adding a class variable is similar to adding a rule:
Mathematica doesn't rally have classes, so it doesn't have class variables. However, many rules can be applied to a single tag, so it has some aspects similar to a class. With that definition, adding a class variable is similar to adding a rule:
<syntaxhighlight lang="mathematica">
<lang Mathematica>
f[a]=1;
f[a]=1;
f[b]=2;
f[b]=2;
f[a]=3;
f[a]=3;
? f</lang>
? f</syntaxhighlight>
Output:
Output:
Global`f
Global`f
Line 737: Line 979:


Here, the two 'variables' can be seen under the single heading 'f'. And of course all of this is done at runtime.
Here, the two 'variables' can be seen under the single heading 'f'. And of course all of this is done at runtime.

=={{header|MiniScript}}==

If the name of the variable to add is known at compile time, then this is just standard class construction:
<syntaxhighlight lang="miniscript">empty = {}
empty.foo = 1</syntaxhighlight>

If the name of the variable to add is itself in a variable, then instead of dot syntax, use normal indexing:

<syntaxhighlight lang="miniscript">empty = {}
varName = "foo"
empty[varName] = 1</syntaxhighlight>

Either method results in a perfectly ordinary class or instance (there is no technical distinction between these in MiniScript), which can be used as usual by subsequent code.


=={{header|Morfa}}==
=={{header|Morfa}}==
To emulate adding a variable to a class instance, Morfa uses user-defined operators <tt>`</tt> and <tt>&lt;-</tt>.
To emulate adding a variable to a class instance, Morfa uses user-defined operators <tt>`</tt> and <tt>&lt;-</tt>.
<lang morfa>
<syntaxhighlight lang="morfa">
import morfa.base;
import morfa.base;


Line 803: Line 1,059:
}
}
}
}
</syntaxhighlight>
</lang>
{{out}}
{{out}}
<pre>
<pre>
30 20
30 20
</pre>

=={{header|Nim}}==
<syntaxhighlight lang="nim">import json
{.experimental: "dotOperators".}
template `.=`(js: JsonNode, field: untyped, value: untyped) =
js[astToStr(field)] = %value
template `.`(js: JsonNode, field: untyped): JsonNode = js[astToStr(field)]
var obj = newJObject()
obj.foo = "bar"
echo(obj.foo)
obj.key = 3
echo(obj.key)</syntaxhighlight>
{{out}}
<pre>
"bar"
3
</pre>
</pre>


Line 814: Line 1,087:
You can put associative references on any object. You can put multiple ones on the same object. They are indexed by a pointer key (typically the address of some dummy variable). You use the functions <code>objc_getAssociatedObject()</code> and <code>objc_setAssociatedObject</code> to get and set them, respectively.
You can put associative references on any object. You can put multiple ones on the same object. They are indexed by a pointer key (typically the address of some dummy variable). You use the functions <code>objc_getAssociatedObject()</code> and <code>objc_setAssociatedObject</code> to get and set them, respectively.


<lang objc>#import <Foundation/Foundation.h>
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/runtime.h>


Line 833: Line 1,106:
}
}
return 0;
return 0;
}</lang>
}</syntaxhighlight>


You can also use a selector as the key, since two selectors with the same content are guaranteed to be equal:
You can also use a selector as the key, since two selectors with the same content are guaranteed to be equal:
<lang objc>#import <Foundation/Foundation.h>
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/runtime.h>


Line 853: Line 1,126:
}
}
return 0;
return 0;
}</lang>
}</syntaxhighlight>


=={{header|Octave}}==
=={{header|Octave}}==
Octave is dynamically typed, and can have fields added in two methods:
Octave is dynamically typed, and can have fields added in two methods:


<lang octave>
<syntaxhighlight lang="octave">
% Given struct "test"
% Given struct "test"
test.b=1;
test.b=1;
test = setfield (test, "c", 3);
test = setfield (test, "c", 3);
</syntaxhighlight>
</lang>


=={{header|ooRexx}}==
=={{header|ooRexx}}==
Line 868: Line 1,141:
===Unknown Method Access===
===Unknown Method Access===
This example traps unknown method calls, then sets or retrieves the values in an encapsulated directory object.
This example traps unknown method calls, then sets or retrieves the values in an encapsulated directory object.
<syntaxhighlight lang="oorexx">
<lang ooRexx>
d = .dynamicvar~new
d = .dynamicvar~new
d~foo = 123
d~foo = 123
Line 907: Line 1,180:
self~init:.dynamicvar
self~init:.dynamicvar


</syntaxhighlight>
</lang>


===Dynamic Method Definitions===
===Dynamic Method Definitions===
An object may be written that can dynamically add methods to itself. This example is similar to the above example, but the UNKNOWN method attaches a getter/setter pair of methods for the name triggering the UNKNOWN call. On all subsequent calls, the attribute methods will get called.
An object may be written that can dynamically add methods to itself. This example is similar to the above example, but the UNKNOWN method attaches a getter/setter pair of methods for the name triggering the UNKNOWN call. On all subsequent calls, the attribute methods will get called.
<syntaxhighlight lang="oorexx">
<lang ooRexx>
d = .dynamicvar~new
d = .dynamicvar~new
d~foo = 123
d~foo = 123
Line 948: Line 1,221:
forward to(self) message(messageName) arguments(arguments)
forward to(self) message(messageName) arguments(arguments)


</syntaxhighlight>
</lang>


=={{header|OxygenBasic}}==
=={{header|OxygenBasic}}==
Simple implementation for making runtime members - supports integer, float and string types.
Simple implementation for making runtime members - supports integer, float and string types.
<lang oxygenbasic>
<syntaxhighlight lang="oxygenbasic">
'=================
'=================
class fleximembers
class fleximembers
Line 1,024: Line 1,297:
a.delete
a.delete


</syntaxhighlight>
</lang>

=={{header|Oz}}==
=={{header|Oz}}==
It is not possible to add variables to instances in Oz. Every object has exactly one class and this association cannot be changed after object creation. Classes themselves are immutable.
It is not possible to add variables to instances in Oz. Every object has exactly one class and this association cannot be changed after object creation. Classes themselves are immutable.
Line 1,030: Line 1,304:
However, classes are also first-class values and are created at runtime. Many of the tasks that are solved with "monkeypatching" in other languages, can be solved by dynamically creating classes in Oz.
However, classes are also first-class values and are created at runtime. Many of the tasks that are solved with "monkeypatching" in other languages, can be solved by dynamically creating classes in Oz.


<lang oz>declare
<syntaxhighlight lang="oz">declare
%% Creates a new class derived from BaseClass
%% Creates a new class derived from BaseClass
%% with an added feature (==public immutable attribute)
%% with an added feature (==public immutable attribute)
Line 1,058: Line 1,332:
in
in
{Show Instance.bar} %% inherited feature
{Show Instance.bar} %% inherited feature
{Show Instance.foo} %% feature of "synthesized" class</lang>
{Show Instance.foo} %% feature of "synthesized" class</syntaxhighlight>


To add a variable number of features and attributes, you can use [http://www.mozart-oz.org/documentation/base/class.html Class.new].
To add a variable number of features and attributes, you can use [http://www.mozart-oz.org/documentation/base/class.html Class.new].


=={{header|Perl}}==
=={{header|Pascal}}==
Works with FPC (tested with version 3.2.2).
{{works with|Perl|5.x}}
<lang perl>package Empty;


This could be done by playing around with the custom variants a bit.
# Constructor. Object is hash.
sub new { return bless {}, shift; }


Let's put the following code in a separate unit:
package main;
<syntaxhighlight lang="pascal">
unit MyObjDef;
{$mode objfpc}{$h+}{$interfaces com}
interface


function MyObjCreate: Variant;
# Object.
my $o = Empty->new;


implementation
# Set runtime variable (key => value).
uses
$o->{'foo'} = 1;</lang>
Variants, Generics.Collections;


var
MyObjType: TInvokeableVariantType;


type
=={{header|Perl 6}}==
IMyObj = interface
{{works with|Rakudo|2015.12}}
procedure SetVar(const aName: string; const aValue: Variant);
You can add variables/methods to a class at runtime by composing in a role. The role only affects that instance, though it is inheritable. An object created from an existing object will inherit any roles composed in with values set to those at the time the role was created. If you want to keep changed values in the new object, clone it instead.
function GetVar(const aName: string): Variant;
<lang perl6>class Bar { } # an empty class
end;


TMyObj = class(TInterfacedObject, IMyObj)
my $object = Bar.new; # new instance
strict private
FMap: specialize TDictionary<string, Variant>;
public
constructor Create;
destructor Destroy; override;
procedure SetVar(const aName: string; const aValue: Variant);
function GetVar(const aName: string): Variant;
end;


TMyData = packed record
role a_role { # role to add a variable: foo,
VType: TVarType;
has $.foo is rw = 2; # with an initial value of 2
Dummy1: array[0..5] of Byte;
}
Dummy2: Pointer;
FObj: IMyObj;
end;


TMyObjType = class(TInvokeableVariantType)
$object does a_role; # compose in the role
procedure Clear(var V: TVarData); override;
procedure Copy(var aDst: TVarData; const aSrc: TVarData; const Indir: Boolean); override;
function GetProperty(var aDst: TVarData; const aData: TVarData; const aName: string): Boolean; override;
function SetProperty(var V: TVarData; const aName: string; const aData: TVarData): Boolean; override;
end;


function MyObjCreate: Variant;
say $object.foo; # prints: 2
begin
$object.foo = 5; # change the variable
VarClear(Result);
say $object.foo; # prints: 5
TMyData(Result).VType := MyObjType.VarType;
TMyData(Result).FObj := TMyObj.Create;
end;


constructor TMyObj.Create;
my $ohno = Bar.new; # new Bar object
begin
#say $ohno.foo; # runtime error, base Bar class doesn't have the variable foo
FMap := specialize TDictionary<string, Variant>.Create;
end;


destructor TMyObj.Destroy;
my $this = $object.new; # instantiate a new Bar derived from $object
begin
say $this.foo; # prints: 2 - original role value
FMap.Free;
inherited;
end;


procedure TMyObj.SetVar(const aName: string; const aValue: Variant);
my $that = $object.clone; # instantiate a new Bar derived from $object copying any variables
begin
say $that.foo; # 5 - value from the cloned object</lang>
FMap.AddOrSetValue(LowerCase(aName), aValue);
That's what's going on underneath, but often people just mix in an anonymous role directly using the <tt>but</tt> operator. Here we'll mix an attribute into a normal integer.
end;
<lang perl6>my $lue = 42 but role { has $.answer = "Life, the Universe, and Everything" }


function TMyObj.GetVar(const aName: string): Variant;
say $lue; # 42
begin
say $lue.answer; # Life, the Universe, and Everything</lang>
if not FMap.TryGetValue(LowerCase(aName), Result) then Result := Null;
On the other hand, mixins are frowned upon when it is possible to compose roles directly into classes (as with Smalltalk traits), so that you get method collision detection at compile time. If you want to change a class at run time, you can also use monkey patching:
end;


procedure TMyObjType.Clear(var V: TVarData);
<lang perl6>use MONKEY-TYPING;
begin
augment class Int {
TMyData(V).FObj := nil;
method answer { "Life, the Universe, and Everything" }
V.VType := varEmpty;
}
end;
say 42.answer; # Life, the Universe, and Everything</lang>

This practice, though allowed, is considered to be Evil Action at a Distance.
procedure TMyObjType.Copy(var aDst: TVarData; const aSrc: TVarData; const Indir: Boolean);
begin
VarClear(Variant(aDst));
TMyData(aDst) := TMyData(aSrc);
end;

function TMyObjType.GetProperty(var aDst: TVarData; const aData: TVarData; const aName: string): Boolean;
begin
Result := True;
Variant(aDst) := TMyData(aData).FObj.GetVar(aName);
end;

function TMyObjType.SetProperty(var V: TVarData; const aName: string; const aData: TVarData): Boolean;
begin
Result := True;
TMyData(V).FObj.SetVar(aName, Variant(aData));
end;

initialization
MyObjType := TMyObjType.Create;
finalization
MyObjType.Free;
end.
</syntaxhighlight>

And main program:
<syntaxhighlight lang="pascal">
program test;
{$mode objfpc}{$h+}
uses
MyObjDef;

var
MyObj: Variant;

begin
MyObj := MyObjCreate;
MyObj.Answer := 42;
MyObj.Foo := 'Bar';
MyObj.When := TDateTime(34121);
WriteLn(MyObj.Answer);
WriteLn(MyObj.Foo);
//check if variable names are case-insensitive, as it should be in Pascal
WriteLn(MyObj.wHen);
end.
</syntaxhighlight>
{{out}}
<pre>
42
Bar
01.06.1993
</pre>

=={{header|Perl}}==
{{works with|Perl|5.x}}
<syntaxhighlight lang="perl">package Empty;

# Constructor. Object is hash.
sub new { return bless {}, shift; }

package main;

# Object.
my $o = Empty->new;

# Set runtime variable (key => value).
$o->{'foo'} = 1;</syntaxhighlight>

=={{header|Phix}}==
{{libheader|Phix/Class}}
Dynamic classes are really just wrappers to per-instance dictionaries, not entirely unlike Go/Kotlin/etc, but with slightly nicer syntax.<br>
Attempting to fetch/store "jelly" on a non-dynamic class would trigger a fatal error, unless said field had been explictly defined.
Needs 0.8.1+
<!--<syntaxhighlight lang="phix">-->
<span style="color: #008080;">class</span> <span style="color: #000000;">wobbly</span> <span style="color: #000000;">dynamic</span>
<span style="color: #000080;font-style:italic;">-- (pre-define a few fields/methods if you like)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">class</span>
<span style="color: #000000;">wobbly</span> <span style="color: #000000;">wobble</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new<span style="color: #0000FF;">(<span style="color: #0000FF;">)</span>
<span style="color: #0000FF;">?<span style="color: #000000;">wobble<span style="color: #0000FF;">.<span style="color: #000000;">jelly</span> <span style="color: #000080;font-style:italic;">-- 0
--?wobble["jelly"] -- for dynamic names use []</span>
<span style="color: #000000;">wobble<span style="color: #0000FF;">.<span style="color: #000000;">jelly</span> <span style="color: #0000FF;">=</span> <span style="color: #008000;">"green"</span>
<span style="color: #0000FF;">?<span style="color: #000000;">wobble<span style="color: #0000FF;">.<span style="color: #000000;">jelly</span> <span style="color: #000080;font-style:italic;">-- "green"
<!--</syntaxhighlight>-->


=={{header|PHP}}==
=={{header|PHP}}==
<lang php>class E {};
<syntaxhighlight lang="php">class E {};


$e=new E();
$e=new E();
Line 1,126: Line 1,513:
$e->{"foo"} = 1; // using a runtime name
$e->{"foo"} = 1; // using a runtime name
$x = "foo";
$x = "foo";
$e->$x = 1; // using a runtime name in a variable</lang>
$e->$x = 1; // using a runtime name in a variable</syntaxhighlight>


=={{header|PicoLisp}}==
=={{header|PicoLisp}}==
In general, all instance variables in PicoLisp are dynamically created at
In general, all instance variables in PicoLisp are dynamically created at
runtime.
runtime.
<lang PicoLisp>: (setq MyObject (new '(+MyClass))) # Create some object
<syntaxhighlight lang="picolisp">: (setq MyObject (new '(+MyClass))) # Create some object
-> $385605941
-> $385605941
: (put MyObject 'newvar '(some value)) # Set variable
: (put MyObject 'newvar '(some value)) # Set variable
Line 1,138: Line 1,525:
$385605941 (+MyClass)
$385605941 (+MyClass)
newvar (some value)
newvar (some value)
-> $385605941</lang>
-> $385605941</syntaxhighlight>


=={{header|Pike}}==
=={{header|Pike}}==
Pike does not allow adding variables to existing objects, but we can design a class that allows us to add variables.
Pike does not allow adding variables to existing objects, but we can design a class that allows us to add variables.
<lang Pike>class CSV
<syntaxhighlight lang="pike">class CSV
{
{
mapping variables = ([]);
mapping variables = ([]);
Line 1,173: Line 1,560:
"greeting"
"greeting"
})
})
</syntaxhighlight>
</lang>


=={{header|Pop11}}==
=={{header|Pop11}}==
Line 1,194: Line 1,581:
it using the 'pop11_compile' procedure.
it using the 'pop11_compile' procedure.


<lang pop11>lib objectclass;
<syntaxhighlight lang="pop11">lib objectclass;


define :class foo;
define :class foo;
Line 1,221: Line 1,608:
met1(bar) => ;;; default value -- false
met1(bar) => ;;; default value -- false
"baz" -> met1(bar);
"baz" -> met1(bar);
met1(bar) => ;;; new value</lang>
met1(bar) => ;;; new value</syntaxhighlight>


=={{header|PowerShell}}==
=={{header|PowerShell}}==
PowerShell allows extending arbitrary object instances at runtime with the <code>Add-Member</code> cmdlet. The following example adds a property ''Title'' to an integer:
PowerShell allows extending arbitrary object instances at runtime with the <code>Add-Member</code> cmdlet. The following example adds a property ''Title'' to an integer:
<lang powershell>$x = 42 `
<syntaxhighlight lang="powershell">$x = 42 `
| Add-Member -PassThru `
| Add-Member -PassThru `
NoteProperty `
NoteProperty `
Title `
Title `
"The answer to the question about life, the universe and everything"</lang>
"The answer to the question about life, the universe and everything"</syntaxhighlight>
Now that property can be accessed:
Now that property can be accessed:
<pre>PS> $x.Title
<pre>PS> $x.Title
Line 1,254: Line 1,641:
=={{header|Python}}==
=={{header|Python}}==


<lang python>class empty(object):
<syntaxhighlight lang="python">class empty(object):
pass
pass
e = empty()</lang>
e = empty()</syntaxhighlight>


If the variable (attribute) name is known at "compile" time (hard-coded):
If the variable (attribute) name is known at "compile" time (hard-coded):


<lang python> e.foo = 1</lang>
<syntaxhighlight lang="python"> e.foo = 1</syntaxhighlight>


If the variable name is determined at runtime:
If the variable name is determined at runtime:
<lang python> setattr(e, name, value)</lang>
<syntaxhighlight lang="python"> setattr(e, name, value)</syntaxhighlight>


'''Note:''' Somewhat counter-intuitively one cannot simply use ''e = object(); e.foo = 1'' because the Python base ''object'' (the ultimate ancestor to all new-style classes) will raise attribute exceptions. However, any normal derivatives of ''object'' can be "monkey patched" at will.
'''Note:''' Somewhat counter-intuitively one cannot simply use ''e = object(); e.foo = 1'' because the Python base ''object'' (the ultimate ancestor to all new-style classes) will raise attribute exceptions. However, any normal derivatives of ''object'' can be "monkey patched" at will.
Line 1,269: Line 1,656:
Because functions are first class objects in Python one can not only add variables to instances. One can add or replace functionality to an instance. Doing so is tricky if one wishes to refer back to other instance attributes since there's no "magic" binding back to "self." One trick is to dynamically define the function to be added, nested within the function that applies the patch like so:
Because functions are first class objects in Python one can not only add variables to instances. One can add or replace functionality to an instance. Doing so is tricky if one wishes to refer back to other instance attributes since there's no "magic" binding back to "self." One trick is to dynamically define the function to be added, nested within the function that applies the patch like so:


<lang python>class empty(object):
<syntaxhighlight lang="python">class empty(object):
def __init__(this):
def __init__(this):
this.foo = "whatever"
this.foo = "whatever"
Line 1,281: Line 1,668:
patch_empty(e)
patch_empty(e)
e.print_output()
e.print_output()
# >>> whatever</lang>
# >>> whatever</syntaxhighlight>
:Note: The name ''self'' is not special; it's merely the pervasive Python convention. In this example I've deliberately used ''this'' in the class definition to underscore this fact. The nested definition could use any name for the "self" object. Because it's nested the value of the object is evaluated at the time that the patch_empty() function is run and thus the function being patched in has a valid reference to the object into which it is being inserted. Other arguments could be passed as necessary. Such techniques are not recommended; however they are possible.
:Note: The name ''self'' is not special; it's merely the pervasive Python convention. In this example I've deliberately used ''this'' in the class definition to underscore this fact. The nested definition could use any name for the "self" object. Because it's nested the value of the object is evaluated at the time that the patch_empty() function is run and thus the function being patched in has a valid reference to the object into which it is being inserted. Other arguments could be passed as necessary. Such techniques are not recommended; however they are possible.

=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2015.12}}
You can add variables/methods to a class at runtime by composing in a role. The role only affects that instance, though it is inheritable. An object created from an existing object will inherit any roles composed in with values set to those at the time the role was created. If you want to keep changed values in the new object, clone it instead.
<syntaxhighlight lang="raku" line>class Bar { } # an empty class

my $object = Bar.new; # new instance

role a_role { # role to add a variable: foo,
has $.foo is rw = 2; # with an initial value of 2
}

$object does a_role; # compose in the role

say $object.foo; # prints: 2
$object.foo = 5; # change the variable
say $object.foo; # prints: 5

my $ohno = Bar.new; # new Bar object
#say $ohno.foo; # runtime error, base Bar class doesn't have the variable foo

my $this = $object.new; # instantiate a new Bar derived from $object
say $this.foo; # prints: 2 - original role value

my $that = $object.clone; # instantiate a new Bar derived from $object copying any variables
say $that.foo; # 5 - value from the cloned object</syntaxhighlight>
That's what's going on underneath, but often people just mix in an anonymous role directly using the <tt>but</tt> operator. Here we'll mix an attribute into a normal integer.
<syntaxhighlight lang="raku" line>my $lue = 42 but role { has $.answer = "Life, the Universe, and Everything" }

say $lue; # 42
say $lue.answer; # Life, the Universe, and Everything</syntaxhighlight>
On the other hand, mixins are frowned upon when it is possible to compose roles directly into classes (as with Smalltalk traits), so that you get method collision detection at compile time. If you want to change a class at run time, you can also use monkey patching:

<syntaxhighlight lang="raku" line>use MONKEY-TYPING;
augment class Int {
method answer { "Life, the Universe, and Everything" }
}
say 42.answer; # Life, the Universe, and Everything</syntaxhighlight>
This practice, though allowed, is considered to be Evil Action at a Distance.


=={{header|REBOL}}==
=={{header|REBOL}}==
<lang rebol>
<syntaxhighlight lang="rebol">
REBOL [
REBOL [
Title: "Add Variables to Class at Runtime"
Title: "Add Variables to Class at Runtime"
Author: oofoe
Date: 2009-12-04
URL: http://rosettacode.org/wiki/Adding_variables_to_a_class_instance_at_runtime
URL: http://rosettacode.org/wiki/Adding_variables_to_a_class_instance_at_runtime
]
]
Line 1,336: Line 1,761:
print [crlf "Fighter squadron:"]
print [crlf "Fighter squadron:"]
foreach pilot squadron [probe pilot]
foreach pilot squadron [probe pilot]
</syntaxhighlight>
</lang>


=={{header|Red}}==
=={{header|Red}}==
<lang Red>person: make object! [
<syntaxhighlight lang="red">person: make object! [
name: none
name: none
age: none
age: none
Line 1,349: Line 1,774:
foreach person people [
foreach person people [
print reduce [person/age "year old" person/name "is good at" any [select person 'skill "nothing"]]
print reduce [person/age "year old" person/name "is good at" any [select person 'skill "nothing"]]
]</lang>
]</syntaxhighlight>


=={{header|Ring}}==
=={{header|Ring}}==
We can add an attribute (or a group of attributes) to the object state using addattribute() function
We can add an attribute (or a group of attributes) to the object state using addattribute() function
<lang ring>o1 = new point
<syntaxhighlight lang="ring">o1 = new point
addattribute(o1,"x")
addattribute(o1,"x")
addattribute(o1,"y")
addattribute(o1,"y")
addattribute(o1,"z")
addattribute(o1,"z")
see o1 {x=10 y=20 z=30}
see o1 {x=10 y=20 z=30}
class point</lang>
class point</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,367: Line 1,792:


=={{header|Ruby}}==
=={{header|Ruby}}==
<lang ruby>class Empty
<syntaxhighlight lang="ruby">class Empty
end
end


Line 1,379: Line 1,804:
f = Empty.new
f = Empty.new
f.foo = 1 # raises NoMethodError
f.foo = 1 # raises NoMethodError
</syntaxhighlight>
</lang>


"class << e" uses the ''singleton class'' of "e", which is an automatic subclass of Empty that has only this single instance. Therefore we added the "foo" accessor only to "e", not to other instances of Empty.
"class << e" uses the ''singleton class'' of "e", which is an automatic subclass of Empty that has only this single instance. Therefore we added the "foo" accessor only to "e", not to other instances of Empty.
Another way of adding a method to a singleton is:
Another way of adding a method to a singleton is:
<lang ruby>yes_no = "Yes"
<syntaxhighlight lang="ruby">yes_no = "Yes"


def yes_no.not
def yes_no.not
Line 1,392: Line 1,817:
p yes_no.not # => "No"
p yes_no.not # => "No"
p yes_no.not # => "Yes"
p yes_no.not # => "Yes"
p "aaa".not # => undefined method `not' for "aaa":String (NoMethodError)</lang>
p "aaa".not # => undefined method `not' for "aaa":String (NoMethodError)</syntaxhighlight>


=={{header|Scala}}==
=={{header|Scala}}==
Line 1,398: Line 1,823:
Since version 2.10 Scala supports dynamic types. Dynamic types have to implement trait ''Dynamic'' and implement methods ''selectDynamic'' and ''updateDynamic''.
Since version 2.10 Scala supports dynamic types. Dynamic types have to implement trait ''Dynamic'' and implement methods ''selectDynamic'' and ''updateDynamic''.


<lang scala>import language.dynamics
<syntaxhighlight lang="scala">import language.dynamics
import scala.collection.mutable.HashMap
import scala.collection.mutable.HashMap


Line 1,409: Line 1,834:
map(name) = value
map(name) = value
}
}
}</lang>
}</syntaxhighlight>


Sample output in the REPL:
Sample output in the REPL:


<lang scala>scala> val a = new A
<syntaxhighlight lang="scala">scala> val a = new A
a: A = A@7b20f29d
a: A = A@7b20f29d


Line 1,420: Line 1,845:


scala> a.foo
scala> a.foo
res10: Any = 42</lang>
res10: Any = 42</syntaxhighlight>


=={{header|Sidef}}==
=={{header|Sidef}}==
<lang ruby>class Empty{};
<syntaxhighlight lang="ruby">class Empty{};
var e = Empty(); # create a new class instance
var e = Empty(); # create a new class instance
e{:foo} = 42; # add variable 'foo'
e{:foo} = 42; # add variable 'foo'
say e{:foo}; # print the value of 'foo'</lang>
say e{:foo}; # print the value of 'foo'</syntaxhighlight>


=={{header|Slate}}==
=={{header|Slate}}==
Slate objects are prototypes:
Slate objects are prototypes:
<lang slate>define: #Empty -> Cloneable clone.
<syntaxhighlight lang="slate">define: #Empty -> Cloneable clone.
define: #e -> Empty clone.
define: #e -> Empty clone.
e addSlotNamed: #foo valued: 1.</lang>
e addSlotNamed: #foo valued: 1.</syntaxhighlight>


=={{header|Smalltalk}}==
=={{header|Smalltalk}}==
Line 1,438: Line 1,863:
This preserves object identity. (by the way: if we remember and reuse these temp classes, we get the core of Google's fast JavaScript interpreter implementation ;-)
This preserves object identity. (by the way: if we remember and reuse these temp classes, we get the core of Google's fast JavaScript interpreter implementation ;-)
{{works with|Smalltalk/X}} (should work with all Smalltalks, though)
{{works with|Smalltalk/X}} (should work with all Smalltalks, though)
<lang smalltalk>|addSlot p|
<syntaxhighlight lang="smalltalk">|addSlot p|


addSlot :=
addSlot :=
Line 1,453: Line 1,878:
newObj := anonCls cloneFrom:obj.
newObj := anonCls cloneFrom:obj.
obj become:newObj.
obj become:newObj.
].</lang>
].</syntaxhighlight>
create a 2D Point object, add a z slot, change and retrieve the z-value, finally inspect it (and see the slots).
create a 2D Point object, add a z slot, change and retrieve the z-value, finally inspect it (and see the slots).
<lang smalltalk>p := Point x:10 y:20.
<syntaxhighlight lang="smalltalk">p := Point x:10 y:20.
addSlot value:p value:'z'.
addSlot value:p value:'z'.
p z:30.
p z:30.
p z.
p z.
p z:40.
p z:40.
p inspect</lang>
p inspect</syntaxhighlight>


The above used a block to perform this operation in privacy. In a real world application, the addSlot code would be added as an extension to the Object class, as in.
The above used a block to perform this operation in privacy. In a real world application, the addSlot code would be added as an extension to the Object class, as in.
<lang smalltalk>!Object methodsFor:'adding slots'!
<syntaxhighlight lang="smalltalk">!Object methodsFor:'adding slots'!


addSlot: slotName
addSlot: slotName
Line 1,477: Line 1,902:
anonCls compile:('%1:v %1 := v' bindWith:slotName).
anonCls compile:('%1:v %1 := v' bindWith:slotName).
newObj := anonCls cloneFrom:self.
newObj := anonCls cloneFrom:self.
self become:newObj.</lang>
self become:newObj.</syntaxhighlight>
then, again create a 2D Point object, add a z slot, change and retrieve the z-value, finally inspect it (and see the slots).
then, again create a 2D Point object, add a z slot, change and retrieve the z-value, finally inspect it (and see the slots).
<lang smalltalk>p := Point x:10 y:20.
<syntaxhighlight lang="smalltalk">p := Point x:10 y:20.
p addSlot:'z'.
p addSlot:'z'. "instance specific added slot"
p z:30.
p z:30.
p z.
p z.
p z:40.
p z:40.
p inspect</lang>
p inspect. "shows 3 slots"
"Point class is unaffected:"

p2 := Point x:20 y:30.
p2 z:40. -> error; Point does not implement z:
p2 inspect. "shows 2 slots"
"but we can create another instance of the enhanced point (even though its an anon class)"
p3 := p class new.
p3 x:1 y:2.
p3 z:4.
p3 inspect. "shows 3 slots"
</syntaxhighlight>


<!--
{{incorrect|Smalltalk|It extends the class (adds a new instance var and new method that will exists even in brand new future instances of that class), not only the particular instance. -- The description of the problem must be reworded then, as it
{{incorrect|Smalltalk|It extends the class (adds a new instance var and new method that will exists even in brand new future instances of that class), not only the particular instance. -- The description of the problem must be reworded then, as it
asks for adding variables to the class, not the instance.
asks for adding variables to the class, not the instance.


CG: commented the bad example; maybe the original author wants to fix it / comment on it.
CG: no, you should read the code carefully: the original class remains unchanged, meaning that future instances of the class ("Point" in the above example) are not affected. Only the one affected instance gets a new class (which is anonymous, as it gets installed into the environment "nil", which means: "nowhere"). Actually, there is no way to get more new instances of that new instance's class because the class of it is only referenced by the changed p. (well, it could be done by using reflection, as with "p class new"). So, the above EXACTLY does what was asked for, whereas the example below is wrongly changing the original class. }}

<lang smalltalk>Object subclass: #Monkey
<syntaxhighlight lang="smalltalk">Object subclass: #Monkey
instanceVariableNames: 'aVar'
instanceVariableNames: 'aVar'
classVariableNames: ''
classVariableNames: ''
Line 1,549: Line 1,985:
aMonkey setX: 10 .
aMonkey setX: 10 .
aMonkey inspect .
aMonkey inspect .
(aMonkey x) printNl .</lang>
(aMonkey x) printNl .</syntaxhighlight>


Output is:
Output is:
Line 1,561: Line 1,997:
x: 10
x: 10
10</pre>
10</pre>
-->


=={{header|Swift}}==
=={{header|Swift}}==
We can use the same associated object mechanism as in Objective-C:
We can use the same associated object mechanism as in Objective-C:


<lang swift>import Foundation
<syntaxhighlight lang="swift">import Foundation
let fooKey = UnsafeMutablePointer<UInt8>.alloc(1)
let fooKey = UnsafeMutablePointer<UInt8>.alloc(1)
Line 1,580: Line 2,017:
} else {
} else {
print("no associated object")
print("no associated object")
}</lang>
}</syntaxhighlight>


=={{header|Tcl}}==
=={{header|Tcl}}==
Line 1,586: Line 2,023:


The code below uses the fact that each object is implemented as a namespace, to add a ''time'' variable to an instance of ''summation'':
The code below uses the fact that each object is implemented as a namespace, to add a ''time'' variable to an instance of ''summation'':
<lang Tcl>% package require TclOO
<syntaxhighlight lang="tcl">% package require TclOO
% oo::class create summation {
% oo::class create summation {
constructor {} {
constructor {} {
Line 1,612: Line 2,049:
% $s value time
% $s value time
now
now
%</lang>
%</syntaxhighlight>
An alternative approach is to expose the (normally hidden) <code>varname</code> method on the object so that you can get a handle for an arbitrary variable in the object.
An alternative approach is to expose the (normally hidden) <code>varname</code> method on the object so that you can get a handle for an arbitrary variable in the object.
<lang tcl>% oo::class create summation {
<syntaxhighlight lang="tcl">% oo::class create summation {
constructor {} {
constructor {} {
variable v 0
variable v 0
Line 1,641: Line 2,078:
% # Show that it is only in one object...
% # Show that it is only in one object...
% $s2 value time
% $s2 value time
can't read "time": no such variable</lang>
can't read "time": no such variable</syntaxhighlight>


=={{header|zkl}}==
=={{header|Wren}}==
Although Wren is dynamically typed, it is not possible to add new variables (or fields as we prefer to call them) to a class at run time. We therefore follow the example of some of the other languages here and use a map field instead.
Once created, class structure is fixed. However, using reflection, you can blow apart the class structure, add what ever and recompile the class (at run time). The REPL does this to store intermediate user results (defined classes, functions, variables, etc). It is ugly, slow and left as an exercise to the reader who cares.
<syntaxhighlight lang="wren">import "io" for Stdin, Stdout


class Birds {
construct new(userFields) {
_userFields = userFields
}
userFields { _userFields }
}


var userFields = {}
{{omit from|Applesoft BASIC}}
System.print("Enter three fields to add to the Birds class:")
for (i in 0..2) {
System.write("\n name : ")
Stdout.flush()
var name = Stdin.readLine()
System.write(" value: ")
Stdout.flush()
var value = Num.fromString(Stdin.readLine())
userFields[name] = value
}

var birds = Birds.new(userFields)

System.print("\nYour fields are:\n")
for (kv in birds.userFields) {
System.print(" %(kv.key) = %(kv.value)")
}</syntaxhighlight>

{{out}}
Sample session:
<pre>
Enter three fields to add to the Birds class:

name : finch
value: 6

name : magpie
value: 7

name : wren
value: 8

Your fields are:

finch = 6
magpie = 7
wren = 8
</pre>

=={{header|XBS}}==
<syntaxhighlight lang="xbs">set Object = {}
Object.Hello = "World";
log(Object.Hello);</syntaxhighlight>
{{out}}
<pre>
World
</pre>

=={{header|zkl}}==
Once created, class structure is fixed. However, using reflection, you can blow apart the class structure, add what ever and recompile the class (at run time). The REPL does this to store intermediate user results (defined classes, functions, variables, etc). It is ugly, slow and left as an exercise to the reader who cares.
{{omit from|6502 Assembly}}
{{omit from|8080 Assembly}}
{{omit from|8086 Assembly}}
{{omit from|68000 Assembly}}
{{omit from|ALGOL 68}}
{{omit from|ALGOL 68}}
{{omit from|Applesoft BASIC}}
{{omit from|ARM Assembly}}
{{omit from|AWK}}
{{omit from|AWK}}
{{omit from|Brainf***}}
{{omit from|Brainf***}}
{{omit from|C}}
{{omit from|C++}}
{{omit from|C++}}
{{omit from|Clojure}}
{{omit from|Clojure}}
{{omit from|C}}
{{omit from|Delphi}}
{{omit from|F Sharp}}
{{omit from|F Sharp}}
{{omit from|Factor}}
{{omit from|Fortran}}
{{omit from|Fortran}}
{{omit from|Free Pascal}}
{{omit from|gnuplot}}
{{omit from|gnuplot}}
{{omit from|Go}}
{{omit from|GUISS}}
{{omit from|GUISS}}
{{omit from|Haskell}}
{{omit from|Haskell}}
{{omit from|Icon}}
{{omit from|Integer BASIC}}
{{omit from|Integer BASIC}}
{{omit from|Java}}
{{omit from|Java}}
Line 1,665: Line 2,168:
{{omit from|Lily}}
{{omit from|Lily}}
{{omit from|M4}}
{{omit from|M4}}
{{omit from|Make}}
{{omit from|Maxima}}
{{omit from|Maxima}}
{{omit from|ML/I}}
{{omit from|ML/I}}
{{omit from|Make}}
{{omit from|Modula-2}}
{{omit from|NetRexx}}
{{omit from|NetRexx}}
{{omit from|Object Pascal}}
{{omit from|OCaml}}
{{omit from|OCaml}}
{{omit from|Octave}}
{{omit from|Octave}}
Line 1,674: Line 2,179:
{{omit from|Pascal}}
{{omit from|Pascal}}
{{omit from|PlainTeX}}
{{omit from|PlainTeX}}
{{omit from|Processing}}
{{omit from|PureBasic}}
{{omit from|PureBasic}}
{{omit from|R}}
{{omit from|TI-83 BASIC}} {{omit from|TI-89 BASIC}} <!-- Does not have objects. -->
{{omit from|Retro}}
{{omit from|Retro}}
{{omit from|Rust}}
{{omit from|R}}
{{omit from|Scheme}}
{{omit from|TI-83 BASIC}}
{{omit from|TI-89 BASIC}} <!-- Does not have objects. -->
{{omit from|UNIX Shell}}
{{omit from|UNIX Shell}}
{{omit from|Z80 Assembly}}
{{omit from|ZX Spectrum Basic}} <!-- Does not have objects. -->
{{omit from|ZX Spectrum Basic}} <!-- Does not have objects. -->

Revision as of 09:20, 6 November 2023

Task
Add a variable to a class instance at runtime
You are encouraged to solve this task according to the task description, using any language you may know.

Demonstrate how to dynamically add variables to an object (a class instance) at runtime.

This is useful when the methods/variables of an instance are based on a data file that isn't available until runtime. Hal Fulton gives an example of creating an OO CSV parser at An Exercise in Metaprogramming with Ruby. This is referred to as "monkeypatching" by Pythonistas and some others.

ActionScript

In ActionScript this can be done using an Object object

var object:Object = new Object();
object.foo = "bar";

Or by creating a dynamic class

package
{
    public dynamic class Foo
    {
        // ...
    }
}
var foo:Foo = new Foo();
foo.bar = "zap";

Ada

Ada is not a dynamically typed language. Yet it supports mix-in inheritance, run-time inheritance and interfaces. These three allow us to achieve the desired effect, however questionably useful it could be. The example declares an interface of the class (Class). Then a concrete type is created (Base). The object E is an instance of Base. Later, at the run time, a new type Monkey_Patch is created such that it refers to E and implements the class interface per delegation to E. Monkey_Patch has a new integer member Foo and EE is an instance of Monkey_Path. For the user EE appears as E with Foo.

with Ada.Text_IO;  use Ada.Text_IO;

procedure Dynamic is
   package Abstract_Class is
      type Class is limited interface;
      function Boo (X : Class) return String is abstract;
   end Abstract_Class;
   use Abstract_Class;

   package Base_Class is
      type Base is new Class with null record;
      overriding function Boo (X : Base) return String;
   end Base_Class;
   
   package body Base_Class is
      function Boo (X : Base) return String is
      begin
         return "I am Class";
      end Boo;
   end Base_Class;
   use Base_Class;

   E : aliased Base;  -- An instance of Base
   
begin
   -- Gone run-time
   declare
      type Monkey_Patch (Root : access Base) is new Class with record
         Foo : Integer := 1;
      end record;
      overriding function Boo (X : Monkey_Patch) return String;
      function Boo (X : Monkey_Patch) return String is
      begin -- Delegation to the base
         return X.Root.Boo;
      end Boo;
      EE : Monkey_Patch (E'Access); -- Extend E
   begin
      Put_Line (EE.Boo & " with" & Integer'Image (EE.Foo));
   end;
end Dynamic;

Sample output:

I am Class with 1

Arturo

define :myClass [name,surname][]

myInstance: to :myClass ["John" "Doe"]
print myInstance

myInstance\age: 35
print myInstance
Output:
[name:John surname:Doe]
[name:John surname:Doe age:35]

AutoHotkey

Works with: AutoHotkey_L
e := {}
e.foo := 1

BBC BASIC

It's not really intended that you should do this, but if you must you can:

      INSTALL @lib$+"CLASSLIB"
      
      REM Create a base class with no members:
      DIM class{method}
      PROC_class(class{})
      
      REM Instantiate the class:
      PROC_new(myobject{}, class{})
      
      REM Add a member at run-time:
      member$ = "mymember#"
      PROCaddmember(myobject{}, member$, 8)
      
      REM Test that the member can be accessed:
      PROCassign("myobject." + member$, "PI")
      PRINT EVAL("myobject." + member$)
      END
      
      DEF PROCaddmember(RETURN obj{}, mem$, size%)
      LOCAL D%, F%, P%
      DIM D% DIM(obj{}) + size% - 1, F% LEN(mem$) + 8
      P% = !^obj{} + 4
      WHILE !P% : P% = !P% : ENDWHILE : !P% = F%
      $$(F%+4) = mem$ : F%!(LEN(mem$) + 5) = DIM(obj{})
      !(^obj{} + 4) = D%
      ENDPROC
      
      DEF PROCassign(v$, n$)
      IF EVAL("FNassign(" + v$ + "," + n$ + ")")
      ENDPROC
      DEF FNassign(RETURN n, v) : n = v : = 0

Bracmat

This solution saves the original members and methods in a variable, using pattern matching. Then, using macro expansion, a new object is created with an additional member variable and also an additional method. Because the new object is assigned to the same variable as the original object, the original object ceases to exist.

( ( struktuur
  = (aMember=) (aMethod=.!(its.aMember))
  )
& new$struktuur:?object
& out$"Object as originally created:"
& lst$object
& A value:?(object..aMember)
& !object:(=?originalMembersAndMethods)
&     new
    $ ( 
      ' ( (anotherMember=)
          (anotherMethod=.!(its.anotherMember))
          ()$originalMembersAndMethods
        )
      )
  : ?object
&   out
  $ "
Object with additional member and method and with 'aMember' already set to some interesting value:"
& lst$object
& some other value:?(object..anotherMember)
& out$"
Call both methods and output their return values."
& out$("aMember contains:" (object..aMethod)$)
& out$("anotherMember contains:" (object..anotherMethod)$)
&);

Output:

Object as originally created:
(object=
=(aMember=) (aMethod=.!(its.aMember)));

Object with additional member and method and with 'aMember' already set to some interesting value:
(object=

=   (anotherMember=)
    (anotherMethod=.!(its.anotherMember))
    (aMember=A value)
    (aMethod=.!(its.aMember)));

Call both methods and output their return values.
aMember contains: A value
anotherMember contains: some other value

C#

Works with: C# version 4.0
// ----------------------------------------------------------------------------------------------
//  
//  Program.cs - DynamicClassVariable
//  
//     Mikko Puonti, 2013
// 
// ----------------------------------------------------------------------------------------------

using System;
using System.Dynamic;

namespace DynamicClassVariable
{
    internal static class Program
    {
        #region Static Members

        private static void Main()
        {
            // To enable late binding, we must use dynamic keyword
            // ExpandoObject readily implements IDynamicMetaObjectProvider which allows us to do some dynamic magic 
            dynamic sampleObj = new ExpandoObject();
            // Adding a new property
            sampleObj.bar = 1;
            Console.WriteLine( "sampleObj.bar = {0}", sampleObj.bar );

            // We can also add dynamically methods and events to expando object 
            // More information: http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx
            // This sample only show very small part of dynamic language features - there is lot's more
            
            Console.WriteLine( "< Press any key >" );
            Console.ReadKey();
        }

        #endregion
    }
}
Output:
sampleObj.bar = 1
< Press any key >

CoffeeScript

# CoffeeScript is dynamic, just like the Javascript it compiles to.
# You can dynamically add attributes to objects.

# First create an object very simply.
e = {}
e.foo = "bar"
e.yo = -> "baz"
console.log e.foo, e.yo()

# CS also has class syntax to instantiate objects, the details of which
# aren't shown here.  The mechanism to add members is the same, though.
class Empty
  # empty class
  
e = new Empty()
e.foo = "bar"
e.yo = -> "baz"
console.log e.foo, e.yo()

Common Lisp

This version adds a new slot only to one instance, not to the whole class.

Library: Closer to MOP
(defun augment-instance-with-slots (instance slots)
  (change-class instance
                (make-instance 'standard-class
                  :direct-superclasses (list (class-of instance))
                  :direct-slots slots)))

Example:

CL-USER> (let* ((instance (make-instance 'foo :bar 42 :baz 69))
                (new-slots '((:name xenu :initargs (:xenu)))))
           (augment-instance-with-slots instance new-slots)
           (reinitialize-instance instance :xenu 666)
           (describe instance))
#<#<STANDARD-CLASS NIL {1003AEE2C1}> {1003AEE271}>
  [standard-object]

Slots with :INSTANCE allocation:
  BAR   = 42
  BAZ   = 69
  XENU  = 666

The following REPL transcript (from LispWorks) shows the definition of a class some-class with no slots, and the creation of an instance of the class. The first attempt to access the slot named slot1 signals an error as there is no such slot. Then the class is redefined to have such a slot, and with a default value of 23. Attempting to access the slot in the preëxisting instance now gives the default value, since the slot has been added to the instance. This behavior is specified in §4.3.6 Redefining Classes of the HyperSpec.

CL-USER 57 > (defclass some-class () ())
#<STANDARD-CLASS SOME-CLASS 200BF63B>

CL-USER 58 > (defparameter *an-instance*
               (make-instance 'some-class))
*AN-INSTANCE*

CL-USER 59 > (slot-value *an-instance* 'slot1)

Error: The slot SLOT1 is missing from #<SOME-CLASS 21F59E37> (of class #<STANDARD-CLASS SOME-CLASS 200BF63B>), when reading the value.
  1 (abort) Return to level 0.
  2 Return to top loop level 0.

Type :b for backtrace, :c <option number> to proceed,  or :? for other options

CL-USER 60 : 1 > :a

CL-USER 61 > (defclass some-class ()
               ((slot1 :initform 23)))
#<STANDARD-CLASS SOME-CLASS 200BF63B>

CL-USER 62 > (slot-value *an-instance* 'slot1)
23

D

struct Dynamic(T) {
    private T[string] vars;

    @property T opDispatch(string key)() pure nothrow {
        return vars[key];
    }

    @property void opDispatch(string key, U)(U value) pure nothrow {
        vars[key] = value;
    }
}

void main() {
    import std.variant, std.stdio;

    // If the type of the attributes is known at compile-time:
    auto d1 = Dynamic!double();
    d1.first = 10.5;
    d1.second = 20.2;
    writeln(d1.first, " ", d1.second);


    // If the type of the attributes is mixed:
    auto d2 = Dynamic!Variant();
    d2.a = "Hello";
    d2.b = 11;
    d2.c = ['x':2, 'y':4];
    d2.d = (int x) => x ^^ 3;
    writeln(d2.a, " ", d2.b, " ", d2.c);
    immutable int x = d2.b.get!int;
}
Output:
10.5 20.2
Hello 11 ['x':2, 'y':4]

If you want Dynamic to be a class the code is similar. If the attribute names aren't known at compile-time, you have to use a more normal syntax:

import std.stdio, std.variant, std.conv;

struct Dyn {
    Variant[string] data;
    alias data this;
}

void main(string[] args) {
    Dyn d;
    const attribute_name = text("attribute_", args.length);
    d[attribute_name] = "something";
    writeln(d[attribute_name]);
}
Output:
something

Elena

ELENA does not support adding a field at run-time but it can be simulated with the help of a mix-in.

ELENA 6.x:

import extensions;

class Extender : BaseExtender
{
   object foo : prop;
    
   constructor(object)
   {
      this object := object
   }
}

public program()
{
   var object := 234;
  
   // extending an object with a field
   object := new Extender(object);

   object.foo := "bar";

   console.printLine(object,".foo=",object.foo);

   console.readChar()
}
Output:
234.foo=bar

Falcon

Classes and singleton objects have a fixed structure which cannot be changed during runtime. However falcon does have capability to add variables/functions at runtime with Prototype based objects. Below are two of the prototype objects that allow adding variables at runtime. These are arrays and dictionaries (hashes for the perl type out there).

Array: In this example we add a function (which prints out the content of the array) and a new value. While we are not technically adding a "variable", this example is presented to show similar type of functionality.

vect = [ 'alpha', 'beta', 'gamma' ]
vect.dump = function ()
  for n in [0: self.len()]
    > @"$(n): ", self[n]
  end
end
vect += 'delta'
vect.dump()

Output from the above:

0: alpha
1: beta
2: gamma
3: delta

Dictionary: In this example we will add a variable through the use of an object from a bless'ed dictionary. We create a new variable called 'newVar' at runtime and assign a string to it. Additionally we assign an external, to the object, function (sub_func) to the variable 'sub'.

function sub_func( value )
  self['prop'] -= value
  return self.prop
end

dict = bless( [
  'prop' => 0,
  'add' => function ( value )
    self.prop += value
    return self.prop
  end ,
  'sub' => sub_func
])

dict[ 'newVar' ] = "I'm Rich In Data"

FBSL

FBSL class instances aren't expandable with additional, directly accessible public methods at runtime once the class template is defined in the user code. But FBSL has an extremely powerful feature -- an ExecLine() function -- which permits the user to execute any additional code on the fly either privately (bypassing the main code flow) or publicly (interacting with the main code). ExecLine() can be used for a variety of applications from the fine-tuning of current tasks to designing application plug-ins or completely standalone code debuggers. The following class instance may be stuffed up at runtime with any code from simple variables to executable private methods and properties.

#APPTYPE CONSOLE

CLASS Growable
	
	PRIVATE:
	
	DIM instructions AS STRING = "Sleep(1)"
	:ExecCode
	DIM dummy AS INTEGER = EXECLINE(instructions, 1)
	
	PUBLIC:
	
	METHOD Absorb(code AS STRING)
		instructions = code
		GOTO ExecCode
	END METHOD
	
	METHOD Yield() AS VARIANT
		RETURN result
	END METHOD
	
END CLASS

DIM Sponge AS NEW Growable()

Sponge.Absorb("DIM b AS VARIANT = 1234567890: DIM result AS VARIANT = b")
PRINT Sponge.Yield()
Sponge.Absorb("b = ""Hello world!"": result = b")
PRINT Sponge.Yield()

PAUSE

Output:

1234567890
Hello world!
Press any key to continue...

Forth

Works with: Forth

Works with any ANS Forth

Needs the FMS-SI (single inheritance) library code located here: http://soton.mpeforth.com/flag/fms/index.html

include FMS-SI.f
include FMS-SILib.f



\ We can add any number of variables at runtime by adding
\ objects of any type to an instance at run time.  The added
\ objects are then accessible via an index number.

:class foo
  object-list inst-objects \ a dynamically growable object container
  :m init: inst-objects init: ;m
  :m add: ( obj -- ) inst-objects add: ;m
  :m at: ( idx -- obj ) inst-objects at: ;m
;class

foo foo1 

: main
  heap> string foo1 add:
  heap> fvar   foo1 add:

  s" Now is the time " 0 foo1 at: !:
  3.14159e             1 foo1 at: !:

  0 foo1 at: p: \ send the print message to indexed object 0
  1 foo1 at: p: \ send the print message to indexed object 1
;

main \ => Now is the time 3.14159


FreeBASIC

' Class ... End Class
' Esta característica aún no está implementada en el compilador.


Go

Translation of: Kotlin


Firstly, Go doesn't have classes or class variables but does have structs (an analogous concept) which consist of fields.

Adding fields to a struct at runtime is not possible as Go is a statically typed, compiled language and therefore the names of all struct fields need to be known at compile time.

However, as in the case of Groovy and Kotlin, we can make it appear as though fields are being added at runtime by using the built-in map type. For example:

package main

import (
    "bufio"
    "fmt"
    "log"
    "os"
)

type SomeStruct struct {
    runtimeFields map[string]string
}

func check(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

func main() {
    ss := SomeStruct{make(map[string]string)}
    scanner := bufio.NewScanner(os.Stdin)
    fmt.Println("Create two fields at runtime: ")
    for i := 1; i <= 2; i++ {
        fmt.Printf("  Field #%d:\n", i)
        fmt.Print("       Enter name  : ")
        scanner.Scan()
        name := scanner.Text()
        fmt.Print("       Enter value : ")
        scanner.Scan()
        value := scanner.Text()
        check(scanner.Err())
        ss.runtimeFields[name] = value
        fmt.Println()
    }
    for {
        fmt.Print("Which field do you want to inspect ? ")
        scanner.Scan()
        name := scanner.Text()
        check(scanner.Err())
        value, ok := ss.runtimeFields[name]
        if !ok {
            fmt.Println("There is no field of that name, try again")
        } else {
            fmt.Printf("Its value is '%s'\n", value)
            return
        }
    }
}
Output:

Sample input/output:

Create two fields at runtime: 
  Field #1:
       Enter name  : a
       Enter value : rosetta

  Field #2:
       Enter name  : b
       Enter value : 64

Which field do you want to inspect ? a
Its value is 'rosetta'

Groovy

Any Groovy class that implements "Object get(String)" and "void set(String, Object)" will have the apparent capability to add new properties. However, this capability will only work as expected with an appropriate implementation, backed by a Map object or something very much like a Map.

class A {
    final x = { it + 25 }
    private map = new HashMap()
    Object get(String key) { map[key] }
    void set(String key, Object value) { map[key] = value }
}

Test:

def a = new A()
a.y = 55
a.z = { println (new Date()); Thread.sleep 5000 }

println a.x(25)
println a.y
(0..2).each(a.z)

println a.q

Output:

50
55
Wed Feb 23 21:33:40 CST 2011
Wed Feb 23 21:33:45 CST 2011
Wed Feb 23 21:33:50 CST 2011
null

Icon and Unicon

Unicon implements object environments with records and supporting procedures for creation, initialization, and methods. To modify an instance you must create a new record then copy, amend, and replace it. Strictly speaking we can't guarantee the replace as there is no way to modify the existing object and we are creating a new instance with extensions. The procedures constructor and fieldnames are needed. This example doesn't do error checking. Here extend takes three arguments, the class instance, a list of new variable names as strings, and an optional list of new values to be assigned. The new instance is returned and the object is replaced by assignment. The caveat here is that if the object was assigned to anything else we will now have two objects floating around with possible side effects. As written this isn't safe from name collisions - aside from local declarations the use of a fixed constructor name uses the global name space. There is a final caveat that needs to be observed - if future implementations of objects change then this could easily stop working.

Note: Unicon can be translated via a command line switch into icon which allows for classes to be shared with Icon code (assuming no other incompatibilities exist).

link ximage

procedure main()
   c1 := foo(1,2)                            # instance of foo
   write("c1:\n",ximage(c1))
   c1 := extend(c1,["c","d"],[8,9])          # 2 new fields
   write("new c1:\n",ximage(c1))
   c1 := extend(c1,["e"],[7])                # 1 more
   write("newest c1:\n",ximage(c1))   
end

class foo(a,b)                               # dummy class
end

procedure extend(instance,newvars,newvals)   #: extend a class instance 
   every put(f := [],fieldnames(instance))   # copy existing fieldnames
   c := ["tempconstructor"] ||| f            # new constructor    
   every put(c,!newvars)                     # append new vars
   t := constructor!c                        # new constructor
   x := t()                                  # new instance
   every x[v := !f] := instance[v]           # same as old instance  
   x.__s := x                                # new self 
   if \newvals then 
      every i := 1 to min(*newvars,*newvals) do 
         x[newvars[i]] := newvals[i]         # add new vars = values   
   return x
end

ximage.icn provides ximage to dump variable contents

Output:

c1:
R_foo__state_1 := foo__state()
   R_foo__state_1.a := 1
   R_foo__state_1.b := 2
new c1:
R_tempconstructor_1 := tempconstructor()
   R_tempconstructor_1.__s := R_tempconstructor_1
   R_tempconstructor_1.__m := R_foo__methods_1 := foo__methods()
   R_tempconstructor_1.a := 1
   R_tempconstructor_1.b := 2
   R_tempconstructor_1.c := 8
   R_tempconstructor_1.d := 9
newest c1:
R_tempconstructor_1 := tempconstructor()
   R_tempconstructor_1.__s := R_tempconstructor_1
   R_tempconstructor_1.__m := R_foo__methods_1 := foo__methods()
   R_tempconstructor_1.a := 1
   R_tempconstructor_1.b := 2
   R_tempconstructor_1.c := 8
   R_tempconstructor_1.d := 9
   R_tempconstructor_1.e := 7

Io

All "instance variables" (or slots in Io nomenclature) are created at runtime.

Empty := Object clone

e := Empty clone
e foo := 1

J

If you assign a value to the name which references a property of a class instance, that name within that instance gets that value.

   C=:<'exampleclass'         NB. this will be our class name
   V__C=: 0                   NB. ensure the class exists
   OBJ1=:conew 'exampleclass' NB. create an instance of our class
   OBJ2=:conew 'exampleclass' NB. create another instance
   V__OBJ1,V__OBJ2            NB. both of our instances exist
0
   W__OBJ1                    NB. instance does not have a W
|value error
   W__OBJ1=: 0                NB. here, we add a W to this instance
   W__OBJ1                    NB. this instance now has a W
0
   W__OBJ2                    NB. our other instance does not
|value error

Java

Adding variables to an object at runtime is not possible in Java which is a statically typed language requiring the names of all class variables to be known at compile time.

However, we can make it appear as though variables are being added at runtime by using a Map or similar structure.

import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public final class AddVariableToClassInstanceAtRuntime {

	public static void main(String[] args) {
		Demonstration demo = new Demonstration();
	    System.out.println("Create two variables at runtime: ");
	    Scanner scanner = new Scanner(System.in);
	    for ( int i = 1; i <= 2; i++ ) {	    	
	        System.out.println("    Variable number " + i + ":");
	        System.out.print("        Enter name: ");
	        String name = scanner.nextLine();
	        System.out.print("        Enter value: ");
	        String value = scanner.nextLine();
	        demo.runtimeVariables.put(name, value);
	        System.out.println();
	    }
	    scanner.close();
	    
	    System.out.println("Two new runtime variables appear to have been created.");
	    for ( Map.Entry<String, Object> entry : demo.runtimeVariables.entrySet() ) {
	    	System.out.println("Variable " + entry.getKey() + " = " + entry.getValue());
	    }	
	}

}

final class Demonstration {
	
	Map<String, Object> runtimeVariables = new HashMap<String, Object>();
	
}
Output:
Create two variables at runtime: 
    Variable number 1:
        Enter name: Test
        Enter value: 42

    Variable number 2:
        Enter name: Item
        Enter value: 3.14

Two new runtime variables appear to have been created.
Variable Item = 3.14
Variable Test = 42

JavaScript

This kind of thing is fundamental to JavaScript, as it's a prototype-based language rather than a class-based one.

e = {}       // generic object
e.foo = 1
e["bar"] = 2    // name specified at runtime

jq

jq's "+" operator can be used to add a key/value pair (or to add multiple key-value pairs) to an existing object at runtime, but jq is a functional programming language, and objects themselves cannot be altered. Thus it may be helpful to introduce a variable, since the value of a variable can in effect be updated. For example:

{"a":1} as $a | ($a + {"b":2}) as $a | $a

Thus the value of $a has undergone the desired transition, that is, its final value is {"a":1, "b":2}. A Javascript-like syntax can also be used to add (or update) a key, for example:

$a|.c = 3
# or equivalently:
$a|.["c"] = 3

Julia

Julia does not allow direct modification of the data member variables of a type, though class methods (just Julia functions) can be added without difficulty. For special situations, such as when parsing an input file, where new data type names may be appropriate, this can be accommodated using a Dict as one of the class variables. For example, consider the below JSON input data for a program processing phone numbers, where the type of phone numbers for the person is unknown until run-time:

{"phoneNumbers": [
    {
      "type": "home",
      "number": "212 555-1234"
    },
    {
      "type": "office",
      "number": "646 555-4567"
    },
    {
      "type": "mobile",
      "number": "123 456-7890"
    }]}

Add the data into a class member that is declared as a Dict structure:

mutable struct Contact
    name::String
    phonenumber::Dict{Any,Any}
end

person = Contact("Jane Doe", Dict())
person.phonenumber["home"] = "212 555-1234"

Kotlin

Adding variables to an object at runtime is not possible in Kotlin (at least in the version targeting the JVM) which is a statically typed language and therefore the names of all class variables need to be known at compile time.

However, as in the case of Groovy, we can make it appear as though variables are being added at runtime by using a Map or similar structure. For example:

// version 1.1.2

class SomeClass {
    val runtimeVariables = mutableMapOf<String, Any>()
}

fun main(args: Array<String>) {
    val sc = SomeClass()
    println("Create two variables at runtime: ")
    for (i in 1..2) {
        println("  Variable #$i:")
        print("       Enter name  : ")
        val name = readLine()!!
        print("       Enter value : ")
        val value = readLine()!!
        sc.runtimeVariables.put(name, value)
        println()
    }
    while (true) {
        print("Which variable do you want to inspect ? ")
        val name = readLine()!!
        val value = sc.runtimeVariables[name]
        if (value == null) {
            println("There is no variable of that name, try again")
        } else {
            println("Its value is '${sc.runtimeVariables[name]}'")
            return
        }
    }
}
Output:

Sample input/output:

Create two variables at runtime:
  Variable #1:
       Enter name  : a
       Enter value : rosetta

  Variable #2:
       Enter name  : b
       Enter value : 64

Which variable do you want to inspect ? a
Its value is 'rosetta'

Latitude

Latitude is prototype-oriented, so adding slots at runtime is very straightforward and common.

myObject := Object clone.

;; Name known at compile-time.
myObject foo := "bar".

;; Name known at runtime.
myObject slot 'foo = "bar".

Lingo

obj = script("MyClass").new()

put obj.foo
-- "FOO"

-- add new property 'bar'
obj.setProp(#bar, "BAR")
put obj.bar
-- "BAR"

Logtalk

Logtalk supports "hot patching" (aka "monkey patching") using a category, which is a first-class entity and a fine grained units of code reuse that can be (virtally) imported by any number of objects but also used for "complementing" an existing object, adding new functionality or patching existing functionality. Complementing cateogries can be enable or disabled globally or on a per object basis.

The following example uses a prototype for simplicity.

% we start by defining an empty object
:- object(foo).

    % ensure that complementing categories are allowed
	:- set_logtalk_flag(complements, allow).

:- end_object.

% define a complementing category, adding a new predicate
:- category(bar,
    complements(foo)).

	:- public(bar/1).
	bar(1).
	bar(2).
	bar(3).

:- end_category.

We can test our example by compiling and loading the two entities above and then querying the object:

| ?- foo::bar(X).
X = 1 ;
X = 2 ;
X = 3
true

LOLCODE

BUKKITs (the all-purpose container type) can be added to at any point during execution, and the SRS operator permits the creation of identifiers from strings. This program and its output demonstrate both by prompting the user for a name and a value, modifying the object accordingly, and then printing the value of the new variable.

HAI 1.3

I HAS A object ITZ A BUKKIT
I HAS A name, I HAS A value

IM IN YR interface
    VISIBLE "R U WANTIN 2 (A)DD A VAR OR (P)RINT 1? "!
    I HAS A option, GIMMEH option

    option, WTF?
    OMG "A"
        VISIBLE "NAME: "!, GIMMEH name
        VISIBLE "VALUE: "!, GIMMEH value
        object HAS A SRS name ITZ value, GTFO
    OMG "P"
        VISIBLE "NAME: "!, GIMMEH name
        VISIBLE object'Z SRS name
    OIC
IM OUTTA YR interface

KTHXBYE

Example run:

R U WANTIN 2 (A)DD A VAR OR (P)RINT 1? A
NAME: foo
VALUE: 42
R U WANTIN 2 (A)DD A VAR OR (P)RINT 1? P
NAME: foo
42

Lua

empty = {}
empty.foo = 1

M2000 Interpreter

Adding y member to an object with a x member which made by a class alfa (a global function). We can make m as a copy of this new group (which is in a container, in a(3)). We can make a pointer to A(3) and handle the new member.

Module checkit {
      class alfa {
            x=5
      }
      \\ a class is a global function which return a group
      Dim a(5)=alfa()
      Print a(3).x=5
      For a(3) {
            group anyname { y=10}
            \\ merge anyname to this (a(3))
            this=anyname
      }
      Print a(3).y=10
      Print Valid(a(2).y)=false
      \\ make a copy of a(3) to m
      m=a(3)
      m.y*=2
      Print m.y=20, a(3).y=10
      \\ make a pointer to a(3) in n
      n->a(3)
      Print n=>y=10
      n=>y+=20
      Print a(3).y=30
     \\ now n points to a(2) 
     n->a(2)   
     Print Valid(n=>y)=false  ' y not exist in a(2)
     Print n is a(2)  ' true
     \\ we don't have types for groups
     Print valid(@n as m)=false  ' n haven't all members of m
     Print valid(@m as n)=true  ' m have all members of n
}
checkit

Mathematica/Wolfram Language

Mathematica doesn't rally have classes, so it doesn't have class variables. However, many rules can be applied to a single tag, so it has some aspects similar to a class. With that definition, adding a class variable is similar to adding a rule:

f[a]=1;
f[b]=2;
f[a]=3;
? f

Output:

Global`f
f[a]=3
f[b]=2

Here, the two 'variables' can be seen under the single heading 'f'. And of course all of this is done at runtime.

MiniScript

If the name of the variable to add is known at compile time, then this is just standard class construction:

empty = {}
empty.foo = 1

If the name of the variable to add is itself in a variable, then instead of dot syntax, use normal indexing:

empty = {}
varName = "foo"
empty[varName] = 1

Either method results in a perfectly ordinary class or instance (there is no technical distinction between these in MiniScript), which can be used as usual by subsequent code.

Morfa

To emulate adding a variable to a class instance, Morfa uses user-defined operators ` and <-.

import morfa.base;

template <T>
public struct Dynamic
{
    var data: Dict<text, T>;
}

// convenience to create new Dynamic instances
template <T>
public property dynamic(): Dynamic<T>
{
    return Dynamic<T>(new Dict<text,T>());
}

// introduce replacement operator for . - a quoting ` operator
public operator ` { kind = infix, precedence = max, associativity = left, quoting = right }
template <T>
public func `(d: Dynamic<T>, name: text): DynamicElementAccess<T>
{
    return DynamicElementAccess<T>(d, name);
}

// to allow implicit cast from the wrapped instance of T (on access)
template <T>
public func convert(dea: DynamicElementAccess<T>): T
{
    return dea.holder.data[dea.name];
}

// cannot overload assignment - introduce special assignment operator
public operator <- { kind = infix, precedence = assign }
template <T>
public func <-(access: DynamicElementAccess<T>, newEl: T): void
{
    access.holder.data[access.name] = newEl;
}

func main(): void
{
    var test = dynamic<int>;
    
    test`a <- 10;
    test`b <- 20;
    test`a <- 30;
    
    println(test`a, test`b);
}

// private helper structure
template <T>
struct DynamicElementAccess
{
    var holder: Dynamic<T>;
    var name: text;
    
    import morfa.io.format.Formatter;
    public func format(formatt: text, formatter: Formatter): text
    {
        return getFormatFunction(holder.data[name])(formatt, formatter);
    }
}
Output:
30 20

Nim

import json
{.experimental: "dotOperators".}
template `.=`(js: JsonNode, field: untyped, value: untyped) =
  js[astToStr(field)] = %value
template `.`(js: JsonNode, field: untyped): JsonNode = js[astToStr(field)]
var obj = newJObject()
obj.foo = "bar"
echo(obj.foo)
obj.key = 3
echo(obj.key)
Output:
"bar"
3

Objective-C

Objective-C doesn't have the ability to add a variable to an instance at runtime. However, since Mac OS X 10.6 and iOS 3.1, it has something that can accomplish a very similar purpose, called "associative references" or "associated objects", which allow you to attach additional objects onto an object without changing its class.

You can put associative references on any object. You can put multiple ones on the same object. They are indexed by a pointer key (typically the address of some dummy variable). You use the functions objc_getAssociatedObject() and objc_setAssociatedObject to get and set them, respectively.

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

static void *fooKey = &fooKey; // one way to define a unique key is a pointer variable that points to itself

int main (int argc, const char *argv[]) {
    @autoreleasepool {

        id e = [[NSObject alloc] init];

        // set
        objc_setAssociatedObject(e, fooKey, @1, OBJC_ASSOCIATION_RETAIN);

        // get
        NSNumber *associatedObject = objc_getAssociatedObject(e, fooKey);
        NSLog(@"associatedObject: %@", associatedObject);

    }
    return 0;
}

You can also use a selector as the key, since two selectors with the same content are guaranteed to be equal:

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

int main (int argc, const char *argv[]) {
    @autoreleasepool {

        id e = [[NSObject alloc] init];

        // set
        objc_setAssociatedObject(e, @selector(foo), @1, OBJC_ASSOCIATION_RETAIN);

        // get
        NSNumber *associatedObject = objc_getAssociatedObject(e, @selector(foo));
        NSLog(@"associatedObject: %@", associatedObject);

    }
    return 0;
}

Octave

Octave is dynamically typed, and can have fields added in two methods:

% Given struct "test"
test.b=1;
test = setfield (test, "c", 3);

ooRexx

ooRexx does not directly expose instance variables to callers. Encapsulated access to instance variables is done via accesser methods for assignment and retrieval. In general, it is not possible to just dynamically add support, but it is possible to construct a class that allows for this to happen.

Unknown Method Access

This example traps unknown method calls, then sets or retrieves the values in an encapsulated directory object.

d = .dynamicvar~new
d~foo = 123
say d~foo

d2 = .dynamicvar2~new
d~bar = "Fred"
say d~bar

-- a class that allows dynamic variables.  Since this is a mixin, this
-- capability can be added to any class using multiple inheritance
::class dynamicvar MIXINCLASS object
::method init
  expose variables
  variables = .directory~new

-- the UNKNOWN method is invoked for all unknown messages.  We turn this
-- into either an assignment or a retrieval for the desired item
::method unknown
  expose variables
  use strict arg messageName, arguments

  -- assignment messages end with '=', which tells us what to do
  if messageName~right(1) == '=' then do
     variables[messageName~left(messageName~length - 1)] = arguments[1]
  end
  else do
      return variables[messageName]
  end


-- this class is not a direct subclass of dynamicvar, but mixes in the
-- functionality using multiple inheritance
::class dynamicvar2 inherit dynamicvar
::method init
  -- mixin init methods are not automatically invoked, so we must
  -- explicitly invoke this
  self~init:.dynamicvar

Dynamic Method Definitions

An object may be written that can dynamically add methods to itself. This example is similar to the above example, but the UNKNOWN method attaches a getter/setter pair of methods for the name triggering the UNKNOWN call. On all subsequent calls, the attribute methods will get called.

d = .dynamicvar~new
d~foo = 123
say d~foo

-- a class that allows dynamic variables.  Since this is a mixin, this
-- capability can be added to any class using multiple inheritance
::class dynamicvar MIXINCLASS object
::method init
  expose variables
  variables = .directory~new

-- the unknown method will get invoked any time an unknown method is
-- used.  This UNKNOWN method will add attribute methods for the given
-- name that will be available on all subsequent uses.
::method unknown
  expose variables
  use strict arg messageName, arguments

  -- check for an assignment or fetch, and get the proper
  -- method name
  if messageName~right(1) == '=' then do
     variableName = messageName~left(messageName~length - 1)
  end
  else do
     variableName = messageName
  end

  -- define a pair of methods to set and retrieve the instance variable.  These are
  -- created at the object scope
  self~setMethod(variableName, 'expose' variableName'; return' variableName)
  self~setMethod(variableName'=', 'expose' variableName'; use strict arg value;' variableName '= value' )

  -- reinvoke the original message.  This will now go to the dynamically added
  methods
  forward to(self) message(messageName) arguments(arguments)

OxygenBasic

Simple implementation for making runtime members - supports integer, float and string types.

'=================
class fleximembers
'=================

indexbase 0
bstring buf, *varl
sys     dp,en

method addVar(string name,dat)
  sys le=len buf
  if dp+16>le then
    buf+=nuls 0x100 : le+=0x100 :
  end if
  @varl=?buf
  varl[en]=name
  varl[en+1]=dat
  dp+=2*sizeof sys
  en+=2 'next slot
end method

method find(string name) as sys
  sys i
  for i=0 to <en step 2
    if name=varl[i] then return i+1
  next
end method

method vars(string name) as string
  sys f=find(name)
  if f then return varl[f]
end method

method VarF(string name) as double
  return vars(name)
end method

method VarI(string name) as sys
  return vars(name)
end method

method vars(string name,dat)
  bstring varl at buf
  sys f=find(name)
  if f then varl[f]=dat
end method

method delete()
  sys i
  sys v at buf
  for i=0 to <en
     freememory v[i]
  next
  freememory ?buf
  ? buf=0 : en=0 : dp=0
end method

end class

'TEST

fleximembers a

a.addVar "p",5
a.addVar "q",4.5
a.addVar "r","123456"

print a.Vars("q")+a.vars("q") 'result 4.54.5
print a.Varf("q")+a.varf("q") 'result 9

a.delete

Oz

It is not possible to add variables to instances in Oz. Every object has exactly one class and this association cannot be changed after object creation. Classes themselves are immutable.

However, classes are also first-class values and are created at runtime. Many of the tasks that are solved with "monkeypatching" in other languages, can be solved by dynamically creating classes in Oz.

declare
  %% Creates a new class derived from BaseClass
  %% with an added feature (==public immutable attribute)
  fun {AddFeature BaseClass FeatureName FeatureValue}
     class DerivedClass from BaseClass
        feat
	   %% "FeatureName" is escaped, otherwise a new variable
	   %% refering to a private feature would be created
           !FeatureName:FeatureValue
     end
  in
     DerivedClass
  end

  class Base
     feat
        bar:1

     meth init
        skip
     end
  end

  Derived = {AddFeature Base foo 2}

  Instance = {New Derived init}
in
  {Show Instance.bar} %% inherited feature
  {Show Instance.foo} %% feature of "synthesized" class

To add a variable number of features and attributes, you can use Class.new.

Pascal

Works with FPC (tested with version 3.2.2).

This could be done by playing around with the custom variants a bit.

Let's put the following code in a separate unit:

unit MyObjDef;
{$mode objfpc}{$h+}{$interfaces com}
interface

function MyObjCreate: Variant;

implementation
uses
  Variants, Generics.Collections;

var
  MyObjType: TInvokeableVariantType;

type
  IMyObj = interface
    procedure SetVar(const aName: string; const aValue: Variant);
    function  GetVar(const aName: string): Variant;
  end;

  TMyObj = class(TInterfacedObject, IMyObj)
  strict private
    FMap: specialize TDictionary<string, Variant>;
  public
    constructor Create;
    destructor Destroy; override;
    procedure SetVar(const aName: string; const aValue: Variant);
    function  GetVar(const aName: string): Variant;
  end;

  TMyData = packed record
    VType:  TVarType;
    Dummy1: array[0..5] of Byte;
    Dummy2: Pointer;
    FObj: IMyObj;
  end;

  TMyObjType = class(TInvokeableVariantType)
    procedure Clear(var V: TVarData); override;
    procedure Copy(var aDst: TVarData; const aSrc: TVarData; const Indir: Boolean); override;
    function  GetProperty(var aDst: TVarData; const aData: TVarData; const aName: string): Boolean; override;
    function  SetProperty(var V: TVarData; const aName: string; const aData: TVarData): Boolean; override;
  end;

function MyObjCreate: Variant;
begin
  VarClear(Result);
  TMyData(Result).VType := MyObjType.VarType;
  TMyData(Result).FObj := TMyObj.Create;
end;

constructor TMyObj.Create;
begin
  FMap := specialize TDictionary<string, Variant>.Create;
end;

destructor TMyObj.Destroy;
begin
  FMap.Free;
  inherited;
end;

procedure TMyObj.SetVar(const aName: string; const aValue: Variant);
begin
  FMap.AddOrSetValue(LowerCase(aName), aValue);
end;

function TMyObj.GetVar(const aName: string): Variant;
begin
  if not FMap.TryGetValue(LowerCase(aName), Result) then Result := Null;
end;

procedure TMyObjType.Clear(var V: TVarData);
begin
  TMyData(V).FObj := nil;
  V.VType := varEmpty;
end;

procedure TMyObjType.Copy(var aDst: TVarData; const aSrc: TVarData; const Indir: Boolean);
begin
  VarClear(Variant(aDst));
  TMyData(aDst) := TMyData(aSrc);
end;

function TMyObjType.GetProperty(var aDst: TVarData; const aData: TVarData; const aName: string): Boolean;
begin
  Result := True;
  Variant(aDst) := TMyData(aData).FObj.GetVar(aName);
end;

function TMyObjType.SetProperty(var V: TVarData; const aName: string; const aData: TVarData): Boolean;
begin
  Result := True;
  TMyData(V).FObj.SetVar(aName, Variant(aData));
end;

initialization
  MyObjType := TMyObjType.Create;
finalization
  MyObjType.Free;
end.

And main program:

program test;
{$mode objfpc}{$h+}
uses
  MyObjDef;

var
  MyObj: Variant;

begin
  MyObj := MyObjCreate;
  MyObj.Answer := 42;
  MyObj.Foo := 'Bar';
  MyObj.When := TDateTime(34121);
  WriteLn(MyObj.Answer);
  WriteLn(MyObj.Foo);
//check if variable names are case-insensitive, as it should be in Pascal
  WriteLn(MyObj.wHen);
end.
Output:
42
Bar
01.06.1993

Perl

Works with: Perl version 5.x
package Empty;

# Constructor. Object is hash.
sub new { return bless {}, shift; }

package main;

# Object.
my $o = Empty->new;

# Set runtime variable (key => value).
$o->{'foo'} = 1;

Phix

Library: Phix/Class

Dynamic classes are really just wrappers to per-instance dictionaries, not entirely unlike Go/Kotlin/etc, but with slightly nicer syntax.
Attempting to fetch/store "jelly" on a non-dynamic class would trigger a fatal error, unless said field had been explictly defined. Needs 0.8.1+

class wobbly dynamic
    -- (pre-define a few fields/methods if you like)
end class
wobbly wobble = new()
?wobble.jelly               -- 0
--?wobble["jelly"]          -- for dynamic names use []
wobble.jelly = "green"
?wobble.jelly               -- "green"

PHP

class E {};

$e=new E();

$e->foo=1;

$e->{"foo"} = 1; // using a runtime name
$x = "foo";
$e->$x = 1; // using a runtime name in a variable

PicoLisp

In general, all instance variables in PicoLisp are dynamically created at runtime.

: (setq MyObject (new '(+MyClass)))       # Create some object
-> $385605941
: (put MyObject 'newvar '(some value))    # Set variable
-> (some value)
: (show MyObject)                         # Show the object
$385605941 (+MyClass)
   newvar (some value)
-> $385605941

Pike

Pike does not allow adding variables to existing objects, but we can design a class that allows us to add variables.

class CSV
{
    mapping variables = ([]);

    mixed `->(string name)
    {
        return variables[name];
    }

    void `->=(string name, mixed value)
    {
        variables[name] = value;
    }

    array _indices()
    {
        return indices(variables);
    }
}

object csv = CSV();
csv->greeting = "hello world";
csv->count = 1;
csv->lang = "Pike";

indices(csv);
Result: ({ /* 3 elements */
              "lang",
              "count",
              "greeting"
         })

Pop11

In Pop11 instance variables (slots) are specified at class creation time and there is no way to add new slot to an instance after its class was created. However, for most practical purposes one can obtain desired effect in different way. Namely, except for a few low-level routines slots in Pop11 are accessed via getter and setter methods. Getters and setters are like ordinary methods, but are automatically defined and "know" low level details of slot access. Pop11 allows dynamic definition of methods, and one can add new methods which work as "getter" and "setter" but do not store data directly in instance. One possibility is to have one instance variable which contains a hastable (this is essentially what Perl solution is doing). Another possibility (used below) is to create na external hashtable. Adding new slots typically make sense if slot name is only known at runtine, so we create method definition (as a list) at runtime and compile it using the 'pop11_compile' procedure.

lib objectclass;

define :class foo;
enddefine;

define define_named_method(method, class);
    lvars method_str = method >< '';
    lvars class_str = class >< '';
    lvars method_hash_str = 'hash_' >< length(class_str) >< '_'
                              >< class_str >< '_' >< length(method_str)
                              >< '_' >< method_str;
    lvars method_hash = consword(method_hash_str);
    pop11_compile([
        lvars ^method_hash = newassoc([]);
        define :method ^method(self : ^class);
            ^method_hash(self);
        enddefine;
        define :method updaterof ^method(val, self : ^class);
            val -> ^method_hash(self);
        enddefine;
    ]);
enddefine;

define_named_method("met1", "foo");
lvars bar = consfoo();
met1(bar) =>  ;;; default value -- false
"baz" -> met1(bar);
met1(bar) =>  ;;; new value

PowerShell

PowerShell allows extending arbitrary object instances at runtime with the Add-Member cmdlet. The following example adds a property Title to an integer:

$x = 42 `
     | Add-Member -PassThru `
        NoteProperty `
        Title `
        "The answer to the question about life, the universe and everything"

Now that property can be accessed:

PS> $x.Title
The answer to the question about life, the universe and everything

or reflected:

PS> $x | Get-Member

   TypeName: System.Int32

Name        MemberType   Definition
----        ----------   ----------
CompareTo   Method       int CompareTo(System.Object value), ...
Equals      Method       bool Equals(System.Object obj), bool...
GetHashCode Method       int GetHashCode()
GetType     Method       type GetType()
GetTypeCode Method       System.TypeCode GetTypeCode()
ToString    Method       string ToString(), string ToString(s...
Title       NoteProperty System.String Title=The answer to th...

While trying to access the same property in another instance will fail:

PS> $y = 42
PS> $y.Title

(which simply causes no output).

Python

class empty(object):
    pass
e = empty()

If the variable (attribute) name is known at "compile" time (hard-coded):

   e.foo = 1

If the variable name is determined at runtime:

   setattr(e, name, value)

Note: Somewhat counter-intuitively one cannot simply use e = object(); e.foo = 1 because the Python base object (the ultimate ancestor to all new-style classes) will raise attribute exceptions. However, any normal derivatives of object can be "monkey patched" at will.

Because functions are first class objects in Python one can not only add variables to instances. One can add or replace functionality to an instance. Doing so is tricky if one wishes to refer back to other instance attributes since there's no "magic" binding back to "self." One trick is to dynamically define the function to be added, nested within the function that applies the patch like so:

class empty(object):
    def __init__(this):
        this.foo = "whatever"

def patch_empty(obj):
    def fn(self=obj):
        print self.foo
    obj.print_output = fn

e = empty()
patch_empty(e)
e.print_output()
# >>> whatever
Note: The name self is not special; it's merely the pervasive Python convention. In this example I've deliberately used this in the class definition to underscore this fact. The nested definition could use any name for the "self" object. Because it's nested the value of the object is evaluated at the time that the patch_empty() function is run and thus the function being patched in has a valid reference to the object into which it is being inserted. Other arguments could be passed as necessary. Such techniques are not recommended; however they are possible.

Raku

(formerly Perl 6)

Works with: Rakudo version 2015.12

You can add variables/methods to a class at runtime by composing in a role. The role only affects that instance, though it is inheritable. An object created from an existing object will inherit any roles composed in with values set to those at the time the role was created. If you want to keep changed values in the new object, clone it instead.

class Bar { }             # an empty class

my $object = Bar.new;     # new instance

role a_role {             # role to add a variable: foo,
   has $.foo is rw = 2;   # with an initial value of 2
}

$object does a_role;      # compose in the role

say $object.foo;          # prints: 2
$object.foo = 5;          # change the variable
say $object.foo;          # prints: 5

my $ohno = Bar.new;       # new Bar object
#say $ohno.foo;           # runtime error, base Bar class doesn't have the variable foo

my $this = $object.new;   # instantiate a new Bar derived from $object
say $this.foo;            # prints: 2 - original role value

my $that = $object.clone; # instantiate a new Bar derived from $object copying any variables
say $that.foo;            # 5 - value from the cloned object

That's what's going on underneath, but often people just mix in an anonymous role directly using the but operator. Here we'll mix an attribute into a normal integer.

my $lue = 42 but role { has $.answer = "Life, the Universe, and Everything" }

say $lue;          # 42
say $lue.answer;   # Life, the Universe, and Everything

On the other hand, mixins are frowned upon when it is possible to compose roles directly into classes (as with Smalltalk traits), so that you get method collision detection at compile time. If you want to change a class at run time, you can also use monkey patching:

use MONKEY-TYPING;
augment class Int {
    method answer { "Life, the Universe, and Everything" }
}
say 42.answer;     # Life, the Universe, and Everything

This practice, though allowed, is considered to be Evil Action at a Distance.

REBOL

REBOL [
	Title: "Add Variables to Class at Runtime"
	URL: http://rosettacode.org/wiki/Adding_variables_to_a_class_instance_at_runtime
]

; As I understand it, a REBOL object can only ever have whatever
; properties it was born with. However, this is somewhat offset by the
; fact that every instance can serve as a prototype for a new object
; that also has the new parameter you want to add.

; Here I create an empty instance of the base object (x), then add the
; new instance variable while creating a new object prototyped from
; x. I assign the new object to x, et voila', a dynamically added
; variable.

x: make object! [] ; Empty object.

x: make x [
	newvar: "forty-two" ; New property.
]

print "Empty object modifed with 'newvar' property:"
probe x

; A slightly more interesting example:

starfighter: make object! [
	model: "unknown"
	pilot: none
]
x-wing: make starfighter [
	model: "Incom T-65 X-wing"
]
	
squadron: reduce [
	make x-wing [pilot: "Luke Skywalker"]
	make x-wing [pilot: "Wedge Antilles"]
	make starfighter [
		model: "Slayn & Korpil B-wing"
		pilot: "General Salm"
	]
]

; Adding new property here.
squadron/1: make squadron/1 [deathstar-removal-expert: yes]

print [crlf "Fighter squadron:"]
foreach pilot squadron [probe pilot]

Red

person: make object! [
  name: none
  age:  none
]

people: reduce [make person [name: "fred" age: 20] make person [name: "paul" age: 21]]
people/1: make people/1 [skill: "fishing"]

foreach person people [
  print reduce [person/age "year old" person/name "is good at" any [select person 'skill "nothing"]]
]

Ring

We can add an attribute (or a group of attributes) to the object state using addattribute() function

o1 = new point
addattribute(o1,"x")
addattribute(o1,"y")
addattribute(o1,"z")
see o1 {x=10 y=20 z=30}
class point
Output:
x: 10.000000
y: 20.000000
z: 30.000000

Ruby

class Empty
end

e = Empty.new
class << e
  attr_accessor :foo
end
e.foo = 1
puts e.foo  # output: "1"

f = Empty.new
f.foo = 1   # raises NoMethodError

"class << e" uses the singleton class of "e", which is an automatic subclass of Empty that has only this single instance. Therefore we added the "foo" accessor only to "e", not to other instances of Empty. Another way of adding a method to a singleton is:

yes_no = "Yes"

def yes_no.not
  replace( self=="Yes" ? "No": "Yes")
end

#Demo:
p yes_no.not # => "No"
p yes_no.not # => "Yes"
p "aaa".not  # => undefined method `not' for "aaa":String (NoMethodError)

Scala

Works with: Scala version 2.10

Since version 2.10 Scala supports dynamic types. Dynamic types have to implement trait Dynamic and implement methods selectDynamic and updateDynamic.

import language.dynamics
import scala.collection.mutable.HashMap

class A extends Dynamic {
  private val map = new HashMap[String, Any]
  def selectDynamic(name: String): Any = {
    return map(name)
  }
  def updateDynamic(name:String)(value: Any) = {
    map(name) = value
  }
}

Sample output in the REPL:

scala> val a = new A
a: A = A@7b20f29d

scala> a.foo = 42
a.foo: Any = 42

scala> a.foo
res10: Any = 42

Sidef

class Empty{};
var e = Empty();    # create a new class instance
e{:foo} = 42;       # add variable 'foo'
say e{:foo};        # print the value of 'foo'

Slate

Slate objects are prototypes:

define: #Empty -> Cloneable clone.
define: #e -> Empty clone.
e addSlotNamed: #foo valued: 1.

Smalltalk

the following addSlot function creates an anonymus class with the additional slot, defines accessor methods and clones a new instance from the given object which becomes the old one. This preserves object identity. (by the way: if we remember and reuse these temp classes, we get the core of Google's fast JavaScript interpreter implementation ;-)

Works with: Smalltalk/X

(should work with all Smalltalks, though)

|addSlot p|

addSlot := 
  [:obj :slotName |
    |anonCls newObj|
    anonCls := obj class 
            subclass:(obj class name,'+') asSymbol 
            instanceVariableNames:slotName 
            classVariableNames:'' 
            poolDictionaries:'' category:nil 
            inEnvironment:nil.
    anonCls compile:('%1 ^  %1' bindWith:slotName).
    anonCls compile:('%1:v %1 := v' bindWith:slotName).
    newObj := anonCls cloneFrom:obj.
    obj become:newObj.
  ].

create a 2D Point object, add a z slot, change and retrieve the z-value, finally inspect it (and see the slots).

p := Point x:10 y:20.
addSlot value:p value:'z'.
p z:30.
p z.
p z:40.
p inspect

The above used a block to perform this operation in privacy. In a real world application, the addSlot code would be added as an extension to the Object class, as in.

!Object methodsFor:'adding slots'!

addSlot: slotName
    |anonCls newObj|

    anonCls := self class 
            subclass:(self class name,'+') asSymbol 
            instanceVariableNames:slotName 
            classVariableNames:'' 
            poolDictionaries:'' category:nil 
            inEnvironment:nil.
    anonCls compile:('%1 ^  %1' bindWith:slotName).
    anonCls compile:('%1:v %1 := v' bindWith:slotName).
    newObj := anonCls cloneFrom:self.
    self become:newObj.

then, again create a 2D Point object, add a z slot, change and retrieve the z-value, finally inspect it (and see the slots).

p := Point x:10 y:20.
p addSlot:'z'.  "instance specific added slot"
p z:30.
p z.
p z:40.
p inspect. "shows 3 slots"
"Point class is unaffected:"
p2 := Point x:20 y:30.
p2 z:40.  -> error; Point does not implement z:
p2 inspect. "shows 2 slots"
"but we can create another instance of the enhanced point (even though its an anon class)"
p3 := p class new.
p3 x:1 y:2.
p3 z:4.
p3 inspect. "shows 3 slots"


Swift

We can use the same associated object mechanism as in Objective-C:

import Foundation
 
let fooKey = UnsafeMutablePointer<UInt8>.alloc(1)
 
class MyClass { }
let e = MyClass()
 
// set
objc_setAssociatedObject(e, fooKey, 1, .OBJC_ASSOCIATION_RETAIN)
 
// get
if let associatedObject = objc_getAssociatedObject(e, fooKey) {
  print("associated object: \(associatedObject)")
} else {
  print("no associated object")
}

Tcl

Works with: Tcl version 8.6

or

Library: TclOO

The code below uses the fact that each object is implemented as a namespace, to add a time variable to an instance of summation:

% package require TclOO
% oo::class create summation {
   constructor {} {
       variable v 0
   }
   method add x {
       variable v
       incr v $x
   }
   method value {{var v}} {
       variable $var
       return [set $var]
   }
   destructor {
       variable v
       puts "Ended with value $v"
   }
}
::summation
% set s [summation new]
% # Do the monkey patch!
% set [info object namespace $s]::time now
now
% # Prove it's really part of the object...
% $s value time
now
%

An alternative approach is to expose the (normally hidden) varname method on the object so that you can get a handle for an arbitrary variable in the object.

% oo::class create summation {
   constructor {} {
       variable v 0
   }
   method add x {
       variable v
       incr v $x
   }
   method value {{var v}} {
       variable $var
       return [set $var]
   }
   destructor {
       variable v
       puts "Ended with value $v"
   }
}
::summation
% set s [summation new]
% set s2 [summation new]
% oo::objdefine $s export varname
% # Do the monkey patch...
% set [$s varname time] "now"
% $s value time
now
% # Show that it is only in one object...
% $s2 value time
can't read "time": no such variable

Wren

Although Wren is dynamically typed, it is not possible to add new variables (or fields as we prefer to call them) to a class at run time. We therefore follow the example of some of the other languages here and use a map field instead.

import "io" for Stdin, Stdout

class Birds {
    construct new(userFields) {
        _userFields = userFields
    }
    userFields { _userFields }
}

var userFields = {}
System.print("Enter three fields to add to the Birds class:")
for (i in 0..2) {
    System.write("\n  name : ")
    Stdout.flush()
    var name = Stdin.readLine()
    System.write("  value: ")
    Stdout.flush()
    var value = Num.fromString(Stdin.readLine())
    userFields[name] = value
}

var birds = Birds.new(userFields)

System.print("\nYour fields are:\n")
for (kv in birds.userFields) {
    System.print("  %(kv.key) = %(kv.value)")
}
Output:

Sample session:

Enter three fields to add to the Birds class:

  name : finch
  value: 6

  name : magpie
  value: 7

  name : wren
  value: 8

Your fields are:

  finch = 6
  magpie = 7
  wren = 8

XBS

set Object = {}
Object.Hello = "World";
log(Object.Hello);
Output:
World

zkl

Once created, class structure is fixed. However, using reflection, you can blow apart the class structure, add what ever and recompile the class (at run time). The REPL does this to store intermediate user results (defined classes, functions, variables, etc). It is ugly, slow and left as an exercise to the reader who cares.