U support Object-Oriented (OOP) syntax with the dot .
operator, but U is not natively Object-Oriented like C++/Java/Python/Ruby/Js. Only user defined operator add OOP on demand. This leads to all advantages of object-oriented programming without compromises:
- better expressiveness for sharing knowledge,
- high development productivity,
- rapid prototyping,
- better maintenance,
- enhanced portability,
- extensible and reusable systems,
- isolated and optimal analysis, debugging.
U Object Oriented Model¶
Using OOP on demand means that U relies on user defined syntax for its OOP model, not its core implementation. U makes it possible to have OOP with/without inheritance, with/without traits, ...
What are Classes ?¶
Classes are closer to C structs than classes in OOP. They are special kinds of user-defined collections where elements have no existence.
If we think of origami, suppose we have a paper cube. In U, the paper cube would be an object – a collection that can contain values – and classes would be the pattern on the flat paper. Without creating space by joining paper sides to create the cube, the cube does not exist and is not a container. U does the same by allocating memory with classes to create objects.
Classes are compile-time collections underneath. They don't exist at run-time. But they allow U to manage efficiently cache-friendly data structures.
Classes have:
- Attributes: values type and specifications for objects,
- Instance Methods: functions attached to classes that process objects with implicit target object
object.meth
, - Class Methods: functions attached to classes that process objects with explicit target object
Class.run(object)
.
What are Objects ?¶
In U, everything is a value. But not all values are objects. Only Values that contain other values are. Usually, in U, the term object is often used instead of value when using the dot operator for method like obj.method
, or when accessing its elements with colon obj:attribute
.
Objects have:
- Instance Variables: values as attributes inside allocated objects,
Objects call Instance or Class methods.
Attributes Visibility¶
Classes can restrict access to their attributes. By default, all attributes and members are private i.e attributes can only be use within the objects. However, you can change this behavior in ugo to make them public by default. It's very useful when prototyping before hardening your system.
In this documentation, we assume that all attributes are public.
Creating Classes and Objects¶
We usually don't need all the paradigms used in OOP (traits, abstract classes, protocols, ...) for all applications and product design phases.
For an MVP, for example, you usually don't need to take time organising your code to deliver quickly. After prototyping, you can think of how better organize your codebase for reuse. For this gradual design, U defines easy keywords for defining classes and objects:
::A
and::An
: for classes definition. Same as::class
,::a
and::an
: for objects creation. Same as::object
, or::new
,::the
: for singleton creation. Singleton ensures there is only one instance of an object. It allows U to better optimize your code. See Singleton.
We use capitalized keywords for classes and lowercase for object creation.
For example:
# Define a structure
::A :Robot, {
::has :speed, :power
::new {: ...
# constructor ...
}
# Class methods
:.check : {: robot
}
# Instance methods
:run ::> \< "Running..."
:jump ::> ...
}
:marvin : ::a @Robot, .speed: 3
# Or
:marvin : @Robot::new(.speed: 3)
# Method call
marvin.run
# Access an element
\< marvin:power
# Method as value
:run_meth : marvin:run
run-meth()
# Prints "Running"
In U, You can easily build sophisticated data structures by adding more OOP behaviors like ::class
, ::traits
, ....
Self¶
::self
allows you to use current object in a method.
Attribute Shorthand¶
::A :Person, :name: @String, :age: @Number
:name: "Al"
:age : 42
::a @Person, .name, .age
# Same as
::a @Person, .name: name, .age: age
Instance Variables¶
Instance Variables start with a dot .
to remind you that you are calling a getter to retrieve a value. Getters/Setters are
Getters and Setters¶
Getters/Setters are generated methods to access attributes from outside the object:
Singleton¶
keyword ::the
create a singleton. Singleton ensures there is only one instance of an object for better performance and safety.
Inheritance vs Composition¶
U inheritance is minimal to allow you to use your rules. Inheritance, composition are simply links between classes either at compile-time or at run-time. The inheritance chain will be used to retrieve a method.
For more details, please read Inheritance vs Composition.
# Dimension must be < 3
::A :Shape, :dim: @<3
::A :Cube, :is_a: @Shape(:dim: 3)
::A :ColoredCube, :is_a: @Cube(), :color: ...
:mycube : (::a @ColoredCube)
\< mycube.dim
# Prints 3
To evaluate mycube.dim
, U executes the following steps:
- lookup for an instance method called dim
through the class chain ColoredCube -> Cube -> Shape
,
- dim
will be found in Shape
class as a getter,
- call Shape.dim(mycube)
Traits¶
Traits are classes without attributes and without type specification. They allow you to model an expected behavior on an object with differents attributes type. They use keywords ::Is
, or ::Can
.
::A :Shape, { ... }
::Can :Rotate, { ... }
::Is :Blue, { ... }
::A :MovingShape, :is: @Blue, :can: @Rotate # Traits
#Inheritance
::A :Rocket, :is_a: @MovingShape
:falcon : ::a @Rocket
You can check for object type with aperture @
Mutually Recursive Classes¶
Mutually recursive classes (MRS) are classes that refer to each other. U ensures there is no cycle in value references that could lead to incorrect behaviors. To define MRS, use keyword ::strec
// <- allows EvenNumber and OddNumber to be recursive!
::strec :EvenNumber: {
...
@OddNumber :num # Refer to OddNumber
},// <- allows EvenNumber and OddNumber to be recursive!
:OddNumber: {
@EvenNumber :num # Refer to EvenNumber
}
Mutually recursive classes are usually created with forward declaration in other languages. U syntax is clearer and safer. For example, you can check literature about how others languages manage mutually recursive classes like a Tree and its Nodes.
Generic Classes¶
Work in progress