Pony语言学习(二):基础类型 之 Class

写在前面的:

这次咱们来唠唠Pony的基础类型,这里说的基础类型指的不是int, string, boolean, float什么内置数据类型,而是Pony中用来定义类型的几种方法,分别是:Class, Primitive, Actor, Trait, Interface, Struct, Type Alias, Type Expressions

Class:

class关键字用于声明一个类。那么什么是一个类呢?一个类就是一种类型,例如狗就是一个类,它可以汪汪叫,可以吃,这是它被定义的行为(方法),它也可以有一个名字,这就是它的属性,也叫做字段。那么我们这里举一个例子:

class Dog
    let dna: String = "DNA"
    var name: String
    
    new create(name': String) => name = name'
    fun scream(): String => "汪汪"
    fun eat(food: String): String => "我吃了" + food

var用来声明变量(这里是可变属性),意思是这个量可以变化,后面跟的是变量名,再之后是该变量的类型,类型和变量名之间用冒号分隔。而let用来声明常量(这里是不可变属性),意思是这个量一旦赋了一个值,就不能再改变它。

fun用来声明函数(这里叫做方法),后面跟一个函数名,再跟一个参数列表,参数列表与返回值类型之间也是用冒号分隔,之后就是=>,这个符号用来告诉编译器,函数头(head)已经结束,现在要编写的是函数体(body)的代码

我们可以发现,参数列表里的参数,和声明变量相似: 参数名: 参数类型。如果参数多的话,用逗号分隔。

new用来声明构造方法。我们暂且不谈什么是构造方法。

一个类在实例化后会产生一个对象,那么什么是对象呢?我们说过,狗可以是一个类,举个例子哈,隔壁王小明买了一条狗,叫旺财,这条狗有名字,也就是说,一条狗(类)的一个属性——名字(name)被定义为 旺财,那么我们管旺财就叫做狗的一个对象。一个类具体(实例)化后,就产生了一个对象。

我们也可以这样理解,类是总称,对象是其中任意一个。

而我们如何具体化类呢?我们就要用到构造方法。在声明一个对象时,Pony会自动帮我们调用构造方法。我们在构造方法的参数列表中定义了一个name'参数,之后会把这个参数赋值给name。因此name有了具体的值,于是就有了一个Dog的对象。

注意!name'这个参数不是一定就要叫这个名字,它可以是_name(其他语言常用),dog_name, dName, dogName等等,这里在name后面加了一个单引号,只是为了区分属性和参数。

记住,类如果要实例化成一个对象,那么这个类中一定要有构造方法!!!系统在实例化对象时,默认调用的是create构造方法,因此你不用写:let dog = Dog.create()。如果你想用其他的构造方法去实例化对象,记住,在实例化对象时,一定要加上这个特定的构造方法名:

class Dog
    //省略
    new has_no_name() =>
        name = "Dog"
actor Main
    new create(env: Env) =>
        let dog = Dog.has_no_name()   //非字段/属性可以使用类型推断
        env.out.print(dog.name) //会输出Dog

 

有些读者会问,1.为什么函数、方法返回值不用return语句,是没有return语句吗?2.难道函数/方法返回都是最后一行的表达式的值吗?

 

Answer1->在通常情况下,函数/方法的确返回的是最后一行的表达式的值。但是,这不代表没有return语句。在Pony中,有return语句

Answer2->函数/方法只在大多数情况下返回最后一行的表达式的值,但是,在某些情况下就需要return语句了,例:

fun demo(n: U64): U64 =>
    if n > 0 then
        return n
    else
        return 0

这里我们把if当做语句来看待。在这个例子中,return语句用来提早返回值。在我们学到控制结构之后,就会明白,if语句其实也可以被当做表达式来看待(类似Rust),所以上面的代码可以这样重写:

fun demo(n: U64): U64 =>
    if n > 0 then
        n
    else
        0

啊呀,忘了解释一下了,这里的U64指的是unsigned int64,即64位的无符号整数。

实例化对象:

我们讲过,实例化对象要使用构造函数,那好,我们来看一个例子:

actor Main
	new create(env: Env) =>
	    let d1: Dog = Dog("旺财")
            env.out.print(d1.scream())

在这个例子中,我们声明了一个常量(因为我们不须在改变它的值),注意它的类型:Dog,实例化对象就像声明变量或常量一样,要先指明类型(其实,如果等号后面的量是明确类型的,可以直接赋值,不必显示声明类型,这个叫做类型推断。属性/字段不能使用类型推断!我们为了教学方便,暂时不说类型推断),之后跟一个类型带一个括号,这就表明要调用构造方法。我们这里向构造方法传送了一个值,我们会得到一个Dog的对象。之后我们可以调用这个对象的方法。

析构方法:

析构方法是在对象被销毁之前,系统默认调用的方法,它只能有一种形式:fun _final()。

总结:

 

  • 声明一个类用class关键字
  • 类中可以有属性(也叫字段),可以是变量或常量,属性/字段不能使用类型推断
  • 类里也可以有方法,方法/函数的声明用fun关键字,后面依次接 1.函数名 2.参数列表(参数的声明方式和属性类似,参数名: 参数类型;参数大于1,要用逗号分隔) 3.返回值类型(注意与参数列表之间的冒号) 4. => 5.函数体
  • 类如果要实例化为一个对象,一定要有构造方法,构造方法用new声明。系统默认调用的是create构造方法,如果你想用其他的构造方法去实例化对象,记住,在实例化对象时,一定要加上这个特定的构造方法名。
    class Dog
        //省略
        new has_no_name() =>
            name = "Dog"
    actor Main
        new create(env: Env) =>
            let dog = Dog.has_no_name()   //非字段/属性可以使用类型推断
            env.out.print(dog.name) //会输出Dog
  • 通常情况下,函数/方法会返回最后一行表达式的值;但是,如果要提前返回值,一定要用return语句
  • 实例化对象和声明变量或常量相似,等号后面的值应是  类名(参数)

写在后面的:

大家学了很久了,辛苦啦!我的教程和官网不一样,大家如果想看些更仔细的,可以去看一看官网的class教程:https://tutorial.ponylang.org/types/classes.html

另外,我想提醒一下大家,类型推断的前提是要有明确类型的值。但是,一个数字就不能被默认推断,因为它的类型可以是U64,U32等等,还有浮点数,它的类型可以是Float32,Float64。如果真的想用类型推断,就要这样做,例:

var integer = U64(10)

因为博主吃过这样的亏,所以想让大家少走弯路。还有一点,print只能输出字符串,欲输出数值变量/常量,要调用string()函数。如下所示:

let a = U64(888)
env.out.print(a.string())

就会输出888啦!这其实就是显式类型转换。(为了安全?)

好啦,我们下次见!欢迎加入Pony语言QQ群261824044!

你可能感兴趣的:(Pony)