Merge pull request #2410 from def-/refobj
Use ref objects with inheritance in Tut2 (fixes #1817)
This commit is contained in:
commit
96d15e9258
3 changed files with 38 additions and 32 deletions
|
|
@ -121,7 +121,7 @@ different; for this a special setter syntax is needed:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
type
|
type
|
||||||
Socket* = object of RootObj
|
Socket* = ref object of RootObj
|
||||||
FHost: int # cannot be accessed from the outside of the module
|
FHost: int # cannot be accessed from the outside of the module
|
||||||
# the `F` prefix is a convention to avoid clashes since
|
# the `F` prefix is a convention to avoid clashes since
|
||||||
# the accessors are named `host`
|
# the accessors are named `host`
|
||||||
|
|
@ -134,8 +134,8 @@ different; for this a special setter syntax is needed:
|
||||||
## getter of hostAddr
|
## getter of hostAddr
|
||||||
s.FHost
|
s.FHost
|
||||||
|
|
||||||
var
|
var s: Socket
|
||||||
s: Socket
|
new s
|
||||||
s.host = 34 # same as `host=`(s, 34)
|
s.host = 34 # same as `host=`(s, 34)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -351,27 +351,27 @@ dispatch.
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
type
|
type
|
||||||
Expression = object of RootObj ## abstract base class for an expression
|
Expression = ref object of RootObj ## abstract base class for an expression
|
||||||
Literal = object of Expression
|
Literal = ref object of Expression
|
||||||
x: int
|
x: int
|
||||||
PlusExpr = object of Expression
|
PlusExpr = ref object of Expression
|
||||||
a, b: ref Expression
|
a, b: Expression
|
||||||
|
|
||||||
method eval(e: ref Expression): int =
|
method eval(e: Expression): int =
|
||||||
# override this base method
|
# override this base method
|
||||||
quit "to override!"
|
quit "to override!"
|
||||||
|
|
||||||
method eval(e: ref Literal): int = return e.x
|
method eval(e: Literal): int = return e.x
|
||||||
|
|
||||||
method eval(e: ref PlusExpr): int =
|
method eval(e: PlusExpr): int =
|
||||||
# watch out: relies on dynamic binding
|
# watch out: relies on dynamic binding
|
||||||
result = eval(e.a) + eval(e.b)
|
result = eval(e.a) + eval(e.b)
|
||||||
|
|
||||||
proc newLit(x: int): ref Literal =
|
proc newLit(x: int): Literal =
|
||||||
new(result)
|
new(result)
|
||||||
result.x = x
|
result.x = x
|
||||||
|
|
||||||
proc newPlus(a, b: ref Expression): ref PlusExpr =
|
proc newPlus(a, b: Expression): PlusExpr =
|
||||||
new(result)
|
new(result)
|
||||||
result.a = a
|
result.a = a
|
||||||
result.b = b
|
result.b = b
|
||||||
|
|
@ -387,8 +387,8 @@ dispatching:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
type
|
type
|
||||||
Thing = object of RootObj
|
Thing = ref object of RootObj
|
||||||
Unit = object of Thing
|
Unit = ref object of Thing
|
||||||
x: int
|
x: int
|
||||||
|
|
||||||
method collide(a, b: Thing) {.inline.} =
|
method collide(a, b: Thing) {.inline.} =
|
||||||
|
|
@ -400,8 +400,9 @@ dispatching:
|
||||||
method collide(a: Unit, b: Thing) {.inline.} =
|
method collide(a: Unit, b: Thing) {.inline.} =
|
||||||
echo "2"
|
echo "2"
|
||||||
|
|
||||||
var
|
var a, b: Unit
|
||||||
a, b: Unit
|
new a
|
||||||
|
new b
|
||||||
collide(a, b) # output: 2
|
collide(a, b) # output: 2
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -568,7 +568,7 @@ the ``of`` operator can be used to determine the object's type.
|
||||||
name*: string # the * means that `name` is accessible from other modules
|
name*: string # the * means that `name` is accessible from other modules
|
||||||
age: int # no * means that the field is hidden
|
age: int # no * means that the field is hidden
|
||||||
|
|
||||||
Student = object of Person # a student is a person
|
Student = ref object of Person # a student is a person
|
||||||
id: int # with an id field
|
id: int # with an id field
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
|
||||||
23
doc/tut2.txt
23
doc/tut2.txt
|
|
@ -56,11 +56,11 @@ Objects have access to their type at runtime. There is an
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
type
|
type
|
||||||
Person = object of RootObj
|
Person = ref object of RootObj
|
||||||
name*: string # the * means that `name` is accessible from other modules
|
name*: string # the * means that `name` is accessible from other modules
|
||||||
age: int # no * means that the field is hidden from other modules
|
age: int # no * means that the field is hidden from other modules
|
||||||
|
|
||||||
Student = object of Person # Student inherits from Person
|
Student = ref object of Person # Student inherits from Person
|
||||||
id: int # with an id field
|
id: int # with an id field
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
@ -69,6 +69,7 @@ Objects have access to their type at runtime. There is an
|
||||||
assert(student of Student) # is true
|
assert(student of Student) # is true
|
||||||
# object construction:
|
# object construction:
|
||||||
student = Student(name: "Anton", age: 5, id: 2)
|
student = Student(name: "Anton", age: 5, id: 2)
|
||||||
|
echo student[]
|
||||||
|
|
||||||
Object fields that should be visible from outside the defining module have to
|
Object fields that should be visible from outside the defining module have to
|
||||||
be marked by ``*``. In contrast to tuples, different object types are
|
be marked by ``*``. In contrast to tuples, different object types are
|
||||||
|
|
@ -82,6 +83,9 @@ no ancestor are implicitly ``final``. You can use the ``inheritable`` pragma
|
||||||
to introduce new object roots apart from ``system.RootObj``. (This is used
|
to introduce new object roots apart from ``system.RootObj``. (This is used
|
||||||
in the GTK wrapper for instance.)
|
in the GTK wrapper for instance.)
|
||||||
|
|
||||||
|
Ref objects should be used whenever inheritance is used. It isn't strictly
|
||||||
|
necessary, but with non-ref objects assignments such as ``let person: Person =
|
||||||
|
Student(id: 123)`` will truncate subclass fields.
|
||||||
|
|
||||||
**Note**: Composition (*has-a* relation) is often preferable to inheritance
|
**Note**: Composition (*has-a* relation) is often preferable to inheritance
|
||||||
(*is-a* relation) for simple code reuse. Since objects are value types in
|
(*is-a* relation) for simple code reuse. Since objects are value types in
|
||||||
|
|
@ -228,7 +232,7 @@ is needed:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
type
|
type
|
||||||
Socket* = object of RootObj
|
Socket* = ref object of RootObj
|
||||||
FHost: int # cannot be accessed from the outside of the module
|
FHost: int # cannot be accessed from the outside of the module
|
||||||
# the `F` prefix is a convention to avoid clashes since
|
# the `F` prefix is a convention to avoid clashes since
|
||||||
# the accessors are named `host`
|
# the accessors are named `host`
|
||||||
|
|
@ -241,8 +245,8 @@ is needed:
|
||||||
## getter of hostAddr
|
## getter of hostAddr
|
||||||
s.FHost
|
s.FHost
|
||||||
|
|
||||||
var
|
var s: Socket
|
||||||
s: Socket
|
new s
|
||||||
s.host = 34 # same as `host=`(s, 34)
|
s.host = 34 # same as `host=`(s, 34)
|
||||||
|
|
||||||
(The example also shows ``inline`` procedures.)
|
(The example also shows ``inline`` procedures.)
|
||||||
|
|
@ -313,8 +317,8 @@ dispatching:
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
type
|
type
|
||||||
Thing = object of RootObj
|
Thing = ref object of RootObj
|
||||||
Unit = object of Thing
|
Unit = ref object of Thing
|
||||||
x: int
|
x: int
|
||||||
|
|
||||||
method collide(a, b: Thing) {.inline.} =
|
method collide(a, b: Thing) {.inline.} =
|
||||||
|
|
@ -326,8 +330,9 @@ dispatching:
|
||||||
method collide(a: Unit, b: Thing) {.inline.} =
|
method collide(a: Unit, b: Thing) {.inline.} =
|
||||||
echo "2"
|
echo "2"
|
||||||
|
|
||||||
var
|
var a, b: Unit
|
||||||
a, b: Unit
|
new a
|
||||||
|
new b
|
||||||
collide(a, b) # output: 2
|
collide(a, b) # output: 2
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue