Core classes and methods used by default by Nit programs and libraries.
This module is the root of the module hierarchy. It provides a very minimal set of classes and services used as a foundation to define other classes and methods.
Each other class implicitly specializes Object,
therefore the services of Object are inherited by every other class and are usable
on each value, including primitive types like integers (Int), strings (String) and arrays (Array).
Note that Object, not Object, is the root of the type hierarchy
since the special value null is not considered as an instance of Object.
self and other the same value?assert 1 + 1 == 2
assert not 1 == "1"
assert 1.to_s == "1"
The exact meaning of same value is left to the subclasses.
Implicitly, the default implementation, is is_same_instance.
The laws of == are the following:
a.is_same_instance(b) implies a == b(a == b) == (b == a)(a == b) and (b == c) implies (a == c)== might not be constant on some objects overtime because of their evolution.
var a = [1]
var b = [1]
var c = [1,2]
assert a == b and not a == c
a.add 2
assert not a == b and a == c
Lastly, == is highly linked with hash and a specific redefinition of == should
usually be associated with a specific redefinition of hash.
ENSURE result implies self.hash == other.hash
self and other different values?!= is equivalent with not ==.
The hash code is used in many data-structures and algorithms to identify objects that might be equal.
Therefore, the precise semantic of hash is highly linked with the semantic of ==
and the only law of hash is that a == b implies a.hash == b.hash.
assert (1+1).hash == 2.hash
assert 1.to_s.hash == "1".hash
hash (like ==) might not be constant on some objects over time because of their evolution.
var a = [1]
var b = [1]
var c = [1,2]
assert a.hash == b.hash
a.add 2
assert a.hash == c.hash
A specific redefinition of == should usually be associated with a specific redefinition of hash.
Note that, unfortunately, a correct definition of hash that is lawful with == is sometime tricky
and a cause of bugs.
Without redefinition, hash is based on the object_id of the instance.
self and other are the same instance (i.e. same identity).var a = new Buffer
var b = a
var c = new Buffer
assert a.is_same_instance(b)
assert not a.is_same_instance(c)
assert a == c
Obviously, the identity of an object is preserved even if the object is mutated.
var x = [1]
var y = x
x.add 2
assert x.is_same_instance(y)
Unless specific code, you should use == instead of is_same_instance because
most of the time is it the semantic (and user-defined) comparison that make sense.
Moreover, relying on is_same_instance on objects you do not control
might have unexpected effects when libraries reuse objects or intern them.
Unless specific code, you should not use this method but
use hash instead.
As its name hints it, the internal hash code, is used internally
to provide a hash value.
It is also used by the inspect method to loosely identify objects
and helps debugging.
var a = "Hello"
var b = a
assert a.object_id == b.object_id
The specific details of the internal hash code it let to the specific engine. The rules are the following:
object_id MUST be invariant for the whole life of the object.object_id.object_id.object_id of a garbage-collected instance MIGHT be reused by new instances.object_id of an object MIGHT be non constant across different executions.For instance, the nitc compiler uses the address of the object in memory
as its object_id.
TODO rename in something like internal_hash_code
This method MUST not be used by programs, it is here for debugging only and can be removed without any notice.
TODO: rename to avoid blocking a good identifier like output.
This method MUST not be used by programs, it is here for debugging only and can be removed without any notice.
TODO: rename to avoid blocking a good identifier like output.
self and other have the same dynamic type.assert 1.is_same_type(2)
assert "Hello".is_same_type("World")
assert not "Hello".is_same_type(2)
The method returns false if the dynamic type of other is a subtype of the dynamic type of self
(or the other way around).
Unless specific code, you should not use this method because it is inconsistent with the fact that a subclass can be used in lieu of a superclass.
Sys is a singleton class, its only instance is accessible from everywhere with sys.
Because of this, methods that should be accessible from everywhere, like print or exit,
are defined in Sys.
Moreover, unless there is an ambiguity with self, the receiver of a call to these methods is implicitly sys.
Basically it means that the two following instructions are equivalent.
print "Hello World"
sys.print "Hello World"
Sys is the class where are defined top-level methods,
i.e. those defined outside of any class like in a procedural language.
Basically it means that
redef class Sys
fun foo do print "hello"
end
is equivalent with
fun foo print "hello"
As a corollary, in a top-level method, self (the current receiver) is always sys.
In a module, the instructions defined outside any classes or methods
(usually called the main of the module) is
an implicit definition of this main method.
Basically it means that the following program
print "Hello World"
is equivalent with
redef class Sys
redef fun main do
print "Hello World"
end
end
When a program starts, the following implicit sequence of instructions is executed
sys = new Sys
sys.run
Whereas the job of the run method is just to execute main.
The only reason of the existence of run is to allow modules to refine it
and inject specific work before or after the main part.
main method to be implemented by subclasses