博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Nim教程【十三】(调查:你会顺手帮博客园点个广告吗?)
阅读量:7039 次
发布时间:2019-06-28

本文共 3654 字,大约阅读时间需要 12 分钟。

类型转换

Nim支持显示类型转换和隐式类型转换

使用casts操作符完成显示类型转换工作,

显示类型转换工作是编译期完成的工作,是位模式的

隐式类型转换也是编译期完成的工作,不是位模式的

让我们来看一下下面的代码

proc getID(x: Person): int =  Student(x).id

在上面的代码中

如果x变量的类型不是Student类型(Person类型是Student类型的父类型)

那么会抛出一个InvalidObjectConversionError异常。

对象变型

通常情况下,可变的对象类型实际意义更大一些

(译注:这是面向对象三大要素之一“多态”的重要组成部分)

来看下面的代码:

# This is an example how an abstract syntax tree could be modelled in Nimtype  NodeKind = enum  # the different node types    nkInt,          # a leaf with an integer value    nkFloat,        # a leaf with a float value    nkString,       # a leaf with a string value    nkAdd,          # an addition    nkSub,          # a subtraction    nkIf            # an if statement  Node = ref NodeObj  NodeObj = object    case kind: NodeKind  # the ``kind`` field is the discriminator    of nkInt: intVal: int    of nkFloat: floatVal: float    of nkString: strVal: string    of nkAdd, nkSub:      leftOp, rightOp: PNode    of nkIf:      condition, thenPart, elsePart: PNodevar n = PNode(kind: nkFloat, floatVal: 1.0)# the following statement raises an `FieldError` exception, because# n.kind's value does not fit:n.strVal = ""

从上面的代码中可以看出

有继承关系的对象之间做类型转换非常简单

访问无效的对象属性会引发一个异常

方法

对象的方法有两个缺点

  • 程序员难以在运行期为一个类型增加方法(或者只能用丑陋的方法才能做到)

  • 很多时候方法的参数是不确定的

Nim为了避免类似的问题,不分配方法到类中

后面我们将了解Nim的动态绑定方法的特性

方法调用

可以使用点操作符调用对象的方法

obj.method(args)

而不是

method(obj,args)

如果没有参数,则可以省略小括号

obj.method

方法调用是不受对象限制的,来看看下面的代码:

echo("abc".len) # is the same as echo(len("abc"))echo("abc".toUpper())echo({'a', 'b', 'c'}.card)stdout.writeln("Hallo") # the same as writeln(stdout, "Hallo")

我们再来看看面向对象的写法

import strutilsstdout.writeln("Give a list of numbers (separated by spaces): ")stdout.write(stdin.readLine.split.map(parseInt).max.`$`)stdout.writeln(" is the maximum!")

是不是感觉很糟糕呢?

属性

请看如下代码来了解对象的属性

type  Socket* = ref object of RootObj    FHost: int # cannot be accessed from the outside of the module               # the `F` prefix is a convention to avoid clashes since               # the accessors are named `host`proc `host=`*(s: var Socket, value: int) {.inline.} =  ## setter of hostAddr  s.FHost = valueproc host*(s: Socket): int {.inline.} =  ## getter of hostAddr  s.FHostvar s: Socketnew ss.host = 34  # same as `host=`(s, 34)

这个Socket类型,有一个host属性,获取这个属性的值时

执行第二个方法,设置这个属性的值时,执行第一个方法

(这个例子中也演示了inline方法)

我们可以在类型中重载方括号,以提供与数组相类似的属性

请看如下代码:

type  Vector* = object    x, y, z: floatproc `[]=`* (v: var Vector, i: int, value: float) =  # setter  case i  of 0: v.x = value  of 1: v.y = value  of 2: v.z = value  else: assert(false)proc `[]`* (v: Vector, i: int): float =  # getter  case i  of 0: result = v.x  of 1: result = v.y  of 2: result = v.z  else: assert(false)

动态指派方法

需要使用method关键字来代替proc关键字

才能使用动态指派的特性

来看下面的代码

type  PExpr = ref object of RootObj ## abstract base class for an expression  PLiteral = ref object of PExpr    x: int  PPlusExpr = ref object of PExpr    a, b: PExpr# watch out: 'eval' relies on dynamic bindingmethod eval(e: PExpr): int =  # override this base method  quit "to override!"method eval(e: PLiteral): int = e.xmethod eval(e: PPlusExpr): int = eval(e.a) + eval(e.b)proc newLit(x: int): PLiteral = PLiteral(x: x)proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b)echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))

再来看看下面的代码

type  Thing = ref object of RootObj  Unit = ref object of Thing    x: intmethod collide(a, b: Thing) {.inline.} =  quit "to override!"method collide(a: Thing, b: Unit) {.inline.} =  echo "1"method collide(a: Unit, b: Thing) {.inline.} =  echo "2"var a, b: Unitnew anew bcollide(a, b) # output: 2

因为决议是从左到右执行的

所以最后一个collide方法优于前面两个collide方法

毕竟a和b都是Unit类型的

注意:Nim不产生虚方法表(C#.net是需要虚方法表的),

但是会生成调用树(这样做可以提升性能表现)

转载地址:http://kxial.baihongyu.com/

你可能感兴趣的文章
HttpClient以及Json传递的一些坑
查看>>
loadrunner11压力测试自学成才!嘎嘎
查看>>
Ext.Net系列:二Event之DirectEvent 示例1-调用事件顺序
查看>>
基于搜狗搜索的微信公众号爬虫实现(C#版本)
查看>>
朋友们谁知道哪里培训PHP比较靠谱的?
查看>>
cnetos6上实现nfs共享
查看>>
若是在做销售源码生意的,还是用 VS2008 省事一些,今天有一个客户没 VS2010 只好再把程序倒退回来...
查看>>
.NET大型C/S系统可动态设置登录窗口的实现参考
查看>>
磁盘的读写原理
查看>>
转-快速编辑Shell命令行
查看>>
【中医养生门户网】注意!春分在于“生、升”,保肝促阳为重
查看>>
SQL 语句技巧--聚合函数的灵活使用
查看>>
Java调用SQL Server的存储过程详解
查看>>
springmvc - SqlSession
查看>>
Json 简介
查看>>
zip()方法对数组进行重新组合
查看>>
60-高级路由:IPv6 静态路由
查看>>
40. Combination Sum II
查看>>
关于适配这件小事的前世今生
查看>>
稳压电源中的谐振变频器的特征
查看>>