论Nim中的 proc 和 method


Nim中,proc 是定义过程的关键字,method 是定义方法的关键字。它们之间根本的区别是proc定义的过程是静态绑定,method定义的方法是动态绑定。谈到静态绑定、动态绑定又会提到重载、重写和多态等方面的内容,如果对上述的一些概念不太理解,可以看我的上一篇博文


过程的重载:

例1:

proc print (): void = 
  echo ("This is empty")

proc print (a:int): void = 
  echo ("int a = ",a)

proc print (a:float): void = 
  echo ("float a = ",a)

print()
print(1)
print(1.0)
Out:
This is empty
int a = 1
float a = 1.0


方法的重载:

例2:

type
  person* = ref object of RootObj
    name*:string
    age*:int

method mm(p:person): int =
  echo p.age,p.name
  echo "method"
  return 0

method mm(p:person,x:int): int = 
  echo "methodint  ",x
  return 0

method mm(p:person,x:float): int = 
  echo "methodfloat  ",x
  return 0

var yrs = person(name:"yrs",age:23)

discard yrs.mm()
discard yrs.mm(3)
discard yrs.mm(3.0)
Out:
23yrs
method
methodint  3
methodfloat  3.0


proc定义的过程,它的参数没有什么要求,可以没有参数,可以是基本类型,也可以是自己定义的类类型。但是method定义的方法,它的参数必须至少含有一个类类型的的参数。也就是说method方法的模块里,必须含有类,同时该方法的参数至少含有一个类类型的参数。


方法的重写与多态:

例3:

#Module: tProcMethod.nim
type Animal* = ref object of RootObj
  name*: string
  age*: int
  
proc SelfIntroduce*(this: Animal): void = echo ("my name is animal")
method vocalize*(this: Animal): string = "..."
method ageHumanYrs*(this: Animal): int = this.age

type Dog* = ref object of Animal
proc SelfIntroduce*(this: Dog): void = echo ("my name is ",this.name)
method vocalize*(this: Dog): string = "woof"
method ageHumanYrs*(this: Dog): int = this.age * 7

type Cat* = ref object of Animal
proc SelfIntroduce*(this: Cat): void = echo ("my name is ",this.name)
method vocalize*(this: Cat): string = "meow"

#Module:testProcMethod.nim
import tProcMethod
var animals : Animal
animals = Dog(name: "Sparky", age: 10)
echo animals.name
echo animals.age
echo animals.vocalize()                 #method方法调用,是通过 实例对象引用.方法名
echo animals.ageHumanYrs()
tProcMethod.SelfIntroduce(animals)      #这里调用proc过程是用 模块名.过程名,在在Windows下用命令行运行文件时,文件名(模块名)的所有字母被认为是小写,
                                         #这里调用过程时要注意模块名字母的大小写。在Linux下则区分大小写。

animals = Cat(name: "Mitten", age: 10)
echo animals.vocalize()
echo animals.ageHumanYrs()
tProcMethod.SelfIntroduce(animals)

Out:
Sparky
10
woof
70
my name is animal
neow
10
my name is animal


方法的重载、重写与多态:

例4:

type
  Far = ref object of RootObj
  bigSon = ref object of Far
  smallSon = ref object of Far
    x: int

method collide(x:Far,y:int)  =                    
  echo "to override!"

method collide(x: bigSon, y: int) =
  echo "big1"

method collide(x: smallSon, y: int) =
  echo "small1"

method collide(x: bigSon, y: float)  =
  echo "2"

method collide(x: bigSon, y: bigSon)  =
  echo "3"

var far: Far
var bigsona, bigsonb: bigSon
var smallsona: smallSon

new far
new bigsona
new bigsonb
new smallsona

collide(far,1)

far = bigsonb
collide(far,1) 
collide(bigsona,1.0) 
collide(bigsona,bigsonb)

far = smallsona
collide(far,1)
Out:
to override!
big1
2
3
small1


在例4中,第二和第三个collide方法分别是bigSon类的方法和smallSon类的方法,它们都实现了对父类方法的重写。第二、四、五collide方法是bigSon类的方法,它们实现了collide方法的重载。


由上面的两个例子可以看出,Nim中的类和方法的存在与Java和Python是不同的。它没有一个明显的界限去区别哪个方法属于哪个类,但是可以通过方法中类类型来辨别(注意动态绑定时,参数是从左至右查询的)。这样就大大降低了程序的可读性,就像例4一样。我们可以像例3一样分开定义来增加程序的可读性。


总结:

1、过程是静态绑定,方法是动态绑定。

2、过程和方法都能重载。

3、过程能够被重写,但是不能实现多态效果。

4、方法能够被重写,能够实现多态效果

5、注意方法和类的关系。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值