introduce object before tuple in the tutorials (#10664)
This commit is contained in:
parent
b081eb4d6d
commit
80992c7a12
2 changed files with 106 additions and 35 deletions
116
doc/tut1.rst
116
doc/tut1.rst
|
|
@ -1441,31 +1441,111 @@ string that is "useless" and replace it with "useful".
|
||||||
Note: alternate ways of writing this are ``b[^8..^2] = "useful"`` or
|
Note: alternate ways of writing this are ``b[^8..^2] = "useful"`` or
|
||||||
as ``b[11..b.len-2] = "useful"`` or as ``b[11..<b.len-1] = "useful"``.
|
as ``b[11..b.len-2] = "useful"`` or as ``b[11..<b.len-1] = "useful"``.
|
||||||
|
|
||||||
Tuples
|
Objects
|
||||||
------
|
-------
|
||||||
|
|
||||||
A tuple type defines various named *fields* and an *order* of the fields.
|
The default type to pack different values together in a single
|
||||||
The constructor ``()`` can be used to construct tuples. The order of the
|
structure with a name is the object type. An object is a value type,
|
||||||
fields in the constructor must match the order in the tuple's definition.
|
which means that when an object is assigned to a new variable all its
|
||||||
Different tuple-types are *equivalent* if they specify fields of
|
components are copied as well.
|
||||||
the same type and of the same name in the same order.
|
|
||||||
|
|
||||||
The assignment operator for tuples copies each component. The notation
|
Each object type ``Foo`` has a constructor ``Foo(field: value, ...)``
|
||||||
``t.field`` is used to access a tuple's field. Another notation is
|
where all of its fields can be initialized. Unspecified fields will
|
||||||
``t[i]`` to access the ``i``'th field. Here ``i`` must be a constant
|
get their default value.
|
||||||
integer.
|
|
||||||
|
.. code-block:: nim
|
||||||
|
type
|
||||||
|
Person = object
|
||||||
|
name: string
|
||||||
|
age: int
|
||||||
|
|
||||||
|
var person1 = Person(name: "Peter", age: 30)
|
||||||
|
|
||||||
|
echo person1.name # "Peter"
|
||||||
|
echo person1.age # 30
|
||||||
|
|
||||||
|
var person2 = person1 # copy of person 1
|
||||||
|
|
||||||
|
person2.age += 14
|
||||||
|
|
||||||
|
echo person1.age # 30
|
||||||
|
echo person2.age # 44
|
||||||
|
|
||||||
|
|
||||||
|
# the order may be changed
|
||||||
|
let person3 = Person(age: 12, name: "Quentin")
|
||||||
|
|
||||||
|
# not every member needs to be specified
|
||||||
|
let person4 = Person(age: 3)
|
||||||
|
# unspecified members will be initialized with their default
|
||||||
|
# values. In this case it is the empty string.
|
||||||
|
doAssert person4.name == ""
|
||||||
|
|
||||||
|
|
||||||
|
Object fields that should be visible from outside the defining module have to
|
||||||
|
be marked with ``*``.
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
:test: "nim c $1"
|
:test: "nim c $1"
|
||||||
|
|
||||||
type
|
type
|
||||||
Person = tuple[name: string, age: int] # type representing a person:
|
Person* = object # the type is visible from other modules
|
||||||
# a person consists of a name
|
name*: string # the field of this type is visible from other modules
|
||||||
# and an age
|
age*: int
|
||||||
|
|
||||||
|
Tuples
|
||||||
|
------
|
||||||
|
|
||||||
|
Tuples are very much like what you have seen so far from objects. They
|
||||||
|
are value types where the assignment operator copies each component.
|
||||||
|
Unlike object types though, tuple types are structurally typed,
|
||||||
|
meaning different tuple-types are *equivalent* if they specify fields of
|
||||||
|
the same type and of the same name in the same order.
|
||||||
|
|
||||||
|
The constructor ``()`` can be used to construct tuples. The order of the
|
||||||
|
fields in the constructor must match the order in the tuple's
|
||||||
|
definition. But unlike objects, a name for the tuple type may not be
|
||||||
|
used here.
|
||||||
|
|
||||||
|
|
||||||
|
Like the object type the notation ``t.field`` is used to access a
|
||||||
|
tuple's field. Another notation that is not available for objects is
|
||||||
|
``t[i]`` to access the ``i``'th field. Here ``i`` must be a constant
|
||||||
|
integer.
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
|
type
|
||||||
|
# type representing a person:
|
||||||
|
# A person consists of a name and an age.
|
||||||
|
Person = tuple
|
||||||
|
name: string
|
||||||
|
age: int
|
||||||
|
|
||||||
|
# Alternative syntax for an equivalent type.
|
||||||
|
PersonX = tuple[name: string, age: int]
|
||||||
|
|
||||||
|
# anonymous field syntax
|
||||||
|
PersonY = (string, int)
|
||||||
|
|
||||||
var
|
var
|
||||||
person: Person
|
person: Person
|
||||||
|
personX: PersonX
|
||||||
|
personY: PersonY
|
||||||
|
|
||||||
person = (name: "Peter", age: 30)
|
person = (name: "Peter", age: 30)
|
||||||
# the same, but less readable:
|
# Person and PersonX are equivalent
|
||||||
|
personX = person
|
||||||
|
|
||||||
|
# Create a tuple with anonymous fields:
|
||||||
|
personY = ("Peter", 30)
|
||||||
|
|
||||||
|
# A tuple with anonymous fields is compatible with a tuple that has
|
||||||
|
# field names.
|
||||||
|
person = personY
|
||||||
|
personY = person
|
||||||
|
|
||||||
|
# Usually used for short tuple initialization syntax
|
||||||
person = ("Peter", 30)
|
person = ("Peter", 30)
|
||||||
|
|
||||||
echo person.name # "Peter"
|
echo person.name # "Peter"
|
||||||
|
|
@ -1484,10 +1564,6 @@ integer.
|
||||||
# --> Error: type mismatch: got (tuple[street: string, number: int])
|
# --> Error: type mismatch: got (tuple[street: string, number: int])
|
||||||
# but expected 'Person'
|
# but expected 'Person'
|
||||||
|
|
||||||
# The following works because the field names and types are the same.
|
|
||||||
var teacher: tuple[name: string, age: int] = ("Mark", 42)
|
|
||||||
person = teacher
|
|
||||||
|
|
||||||
Even though you don't need to declare a type for a tuple to use it, tuples
|
Even though you don't need to declare a type for a tuple to use it, tuples
|
||||||
created with different field names will be considered different objects despite
|
created with different field names will be considered different objects despite
|
||||||
having the same field types.
|
having the same field types.
|
||||||
|
|
@ -1519,6 +1595,8 @@ variables! For example:
|
||||||
echo badname
|
echo badname
|
||||||
echo badext
|
echo badext
|
||||||
|
|
||||||
|
Fields of tuples are always public, they don't need to be explicity
|
||||||
|
marked to be exported, unlike for example fields in an object type.
|
||||||
|
|
||||||
Reference and pointer types
|
Reference and pointer types
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
|
||||||
25
doc/tut2.rst
25
doc/tut2.rst
|
|
@ -40,18 +40,16 @@ and more efficient code. In particular, preferring composition over inheritance
|
||||||
is often the better design.
|
is often the better design.
|
||||||
|
|
||||||
|
|
||||||
Objects
|
Inheritance
|
||||||
-------
|
-----------
|
||||||
|
|
||||||
Like tuples, objects are a means to pack different values together in a
|
Inheritance in Nim is entirely optional. To enable inheritance with
|
||||||
structured way. However, objects provide many features that tuples do not:
|
runtime type information the object needs to inherit from
|
||||||
They provide inheritance and information hiding. Because objects encapsulate
|
``RootObj``. This can be done directly, or indirectly by
|
||||||
data, the ``T()`` object constructor should only be used internally and the
|
inheriting from an object that inherits from ``RootObj``. Usually
|
||||||
programmer should provide a proc to initialize the object (this is called
|
types with inheritance are also marked as ``ref`` types even though
|
||||||
a *constructor*).
|
this isn't strictly enforced. To check at runtime if an object is of a certain
|
||||||
|
type, the ``of`` operator can be used.
|
||||||
Objects have access to their type at runtime. There is an
|
|
||||||
``of`` operator that can be used to check the object's type:
|
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
:test: "nim c $1"
|
:test: "nim c $1"
|
||||||
|
|
@ -71,11 +69,6 @@ Objects have access to their type at runtime. There is an
|
||||||
student = Student(name: "Anton", age: 5, id: 2)
|
student = Student(name: "Anton", age: 5, id: 2)
|
||||||
echo student[]
|
echo student[]
|
||||||
|
|
||||||
Object fields that should be visible from outside the defining module have to
|
|
||||||
be marked by ``*``. In contrast to tuples, different object types are
|
|
||||||
never *equivalent*. New object types can only be defined within a type
|
|
||||||
section.
|
|
||||||
|
|
||||||
Inheritance is done with the ``object of`` syntax. Multiple inheritance is
|
Inheritance is done with the ``object of`` syntax. Multiple inheritance is
|
||||||
currently not supported. If an object type has no suitable ancestor, ``RootObj``
|
currently not supported. If an object type has no suitable ancestor, ``RootObj``
|
||||||
can be used as its ancestor, but this is only a convention. Objects that have
|
can be used as its ancestor, but this is only a convention. Objects that have
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue