I'm designing a programming language for a game, to be used as the main way of interacting with the game, as opposed to using other methods of control, such as the arrow keys or mouse. My plan is to have the user control game objects through objects in the language.
if unit1.health > 20 {
unit1.attack(Enemies.enemy1)
}
Where unit1
and enemy1
are the objects. This can be done relatively easily, however, I would also like the language that the user interacts with to be an actual language, and for the game objects like unit1
to behave similarly to objects created by the user.
I don't plan on adding classes or something similar. All attributes of an object are public by default and read-only, and methods are just attributes that are function objects. You also can't add attributes to an object. The only time the user can access the innards of an object is upon creation, as this is necessary to restrict the user from changing game objects.
Is there any way to add a feature to the language that allows the user to do something like inheritance or something that allows easily writing complex code, while still keeping the language "pure" and simple?
Right now, the most you can do is something like:
fake_class = function(x, y) {
{
self.x = x
self.y = y
z = "hi" // private
self.change_x_and_print_z = function(new) {
self.x = new
print(z)
}
}
}
new_obj = fake_class(4, 5)
But I can think of any way to extend the object, as it is read-only and only mutable from within itself.
2 Answers 2
Make it possible to create a new object as a clone of an existing object with new properties.
So for example:
function Base() {
z = 5
return {
x: 2,
y: 4,
print_z: function() {
print(z)
}
}
}
function Child() {
return {
...Base(), // start with copy of base
g: 5,
h: 3, // add my own stuff
}
}
-
So I would have to give the user a
copy
function that essentially unpacks the contents of the object? eg{copy(Base())}
is equivalent toBase()
. Would this behave well with built-in game objects likeunit1
?Vityou– Vityou12/16/2017 02:56:55Commented Dec 16, 2017 at 2:56 -
@Vityou, that depends on what you mean by "behaves well".Winston Ewert– Winston Ewert12/16/2017 03:12:24Commented Dec 16, 2017 at 3:12
-
I answered my question while I was writing it, but for those who want to know, it was "I mean, since the game objects like
unit1
would be injected into the global environment during the game, and since they have methods that do things externally in the actual game, would copyingunit1
for example let the user has access to anything they shouldn't?", But I don't see any reason that it would do anything like that.Vityou– Vityou12/16/2017 03:41:07Commented Dec 16, 2017 at 3:41 -
I noticed that this approach would not work well with private attributes, as the user could access them by making a copy of an object, and adding a method that returns the value of a private attribute. Is there any way to deal with this?Vityou– Vityou12/17/2017 06:11:19Commented Dec 17, 2017 at 6:11
-
I was thinking like the javascript model where the "private" attributes are actually variables in a closure. They aren't actually attributes on the object at all, but exist in a shared state only accessible to the functions defined there. When you create a copy of the object, you copy these functions but they still refer to the original closure.Winston Ewert– Winston Ewert12/17/2017 06:59:15Commented Dec 17, 2017 at 6:59
There are several alternatives to class-based inheritance that have already been explored
Prototype Delegation: objects can have one or more special references to other objects. When an object does not understand a message, the message is forwarded to the objects referenced by those special references. Some of the first languages that explored this idea were Self and Act-1, the first commercial one was NewtonScript, and the most famous one is ECMAScript. Design decisions are: single (ECMAScript) or multiple (Self) delegation, and whether or not those references are "magical" (ECMAScript) or just regular fields that you can assign to at will (Self).
Mixin Inheritance: Mixins can be thought of as "classes parameterized over their superclass" or as "composable bags of methods".
Trait Composition: Traits are kind-of like Mixins with declared dependencies and conflict resolution (e.g. Method Hiding and Renaming).
The most simple one of these, conceptually, is Prototype Delegation. It is also the one the users will most likely be familiar with, if they have dabbled in web programming.
In Self, prototypes are just regular fields whose name ends with an asterisk *
. Messages are re-sent to the fields in alphabetical order, until either someone answers or a doesNotUnderstand:
message is generated, which then again follows the same lookup rules. If the doesNotUnderstand:
message also is not answered, a NoMethodFoundError
exception is raised.
Since prototypes are just regular fields, you can create, delete, and re-assign them at will, just like every other field.
-
I would like for the child object to have access to a copy of the parent's private variables, it doesn't seem like this is possible in any of these methods.Vityou– Vityou12/16/2017 15:40:02Commented Dec 16, 2017 at 15:40
-
It is possible if you make it possible. It depends how you implement it.Jörg W Mittag– Jörg W Mittag12/16/2017 18:21:12Commented Dec 16, 2017 at 18:21
-
Yes, but that includes more "magic" on the user side than a simple
copy
function. I don't believe a field behaving as something more than a field is intuitive.Vityou– Vityou12/16/2017 18:25:51Commented Dec 16, 2017 at 18:25
Explore related questions
See similar questions with these tags.
delete
operator same with python and lua...