zoukankan      html  css  js  c++  java
  • Scala:(四) 方法、函数、Trait

    scala中既有函数也有方法,在大多数情况下,不用理会其区别也可正常使用。但有时候还是要区分其异同。
    Scala 有方法与函数,二者在语义上的区别很小。Scala 方法是类的一部分,而函数是一个对象可以赋值给一个变量。换句话来说在类中定义的函数即是方法。

    有些翻译上函数(function)与方法(method)是没有区别的。在写这篇博客的过程中,也参考了一些资料,但大都不能令我满意。所以,知道即可,不要过于追究这劳什子,scala是一门语言,语言自然以使用为第一要务。

    方法

    Scala中的方法跟Java的方法一样,方法是组成类的一部分。方法有名字、类型签名,有时方法上还有注解,以及方法的功能实现代码(字节码)
    我们来定义看一个最经典的方法

    函数

    再来定义一个函数

    其主要区别为:

    在函数式编程语言中,函数是“头等公民”,它可以像任何其他数据类型一样被传递和操作
    函数定义语法 用def来定义
    可以定义传入的参数,要指定传入参数的类型
    方法可以写返回值的类型也可以不写,会自动推断,有时候不能省略,必须写,比如在递归函数中或者函数的返回值是函数类型的时候。
    scala中函数有返回值时,可以写return,也可以不写return,会把函数中最后一行当做结果返回。当写return时,必须要写函数的返回值。
    如果返回值可以一行搞定,可以将{}省略不写
    传递给方法的参数可以在方法中使用,并且scala规定方法的传过来的参数为val的,不是var的。
    如果去掉方法体前面的等号,那么这个方法返回类型必定是Unit的。这种说法无论方法体里面什么逻辑都成立,scala可以把任意类型转换为Unit.假设,里面的逻辑最后返回了一个string,那么这个返回值会被转换成Unit,并且值会被丢弃。
    函数也可作为参数传递到方法里

    方法也可转为函数

    方法及函数的调用

    基本使用与java也类似。同样可以点出来,各种操作符也是可以使用的。
    Scala中的+ - * / %等操作符的作用与Java一样,位操作符 & | ^ >> <<也一样。只是有一点特别的:这些操作符实际上是方法。

    a + b
    是如下方法调用的简写:
    a.+(b)
    a 方法 b可以写成 a.方法(b)
    

    递归函数

    注:递归函数的返回值是必须写的

        /**
         * 递归函数 
         * 5的阶乘
         */
        def fun2(num :Int) :Int= {
          if(num == 1)
            num
          else 
            num * fun2(num-1)  //将函数也作为返回值,直到 num==1
        }
        print(fun2(5))
    
    

    参数默认值及可变形参

    scala与java类似,参数同样可以有默认值,且参数个数也可以是不定的

    默认值的函数中,如果传入的参数个数与函数定义相同,则传入的数值会覆盖默认值。
    如果不想覆盖默认值,传入的参数个数小于定义的函数的参数,则需要指定参数名称。

    def fun3(a :Int = 10,b:Int) = {
          println(a+b)
        }
        fun3(b=2)
    

    对于参数不定的,参数之间要用逗号隔开

    def fun4(elements :Int*)={
          var sum = 0;
          for(elem <- elements){
            sum += elem
          }
          sum
        }
        println(fun4(1,2,3,4))
    

    Trait

    Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。与接口不同的是,它还可以定义属性和方法的实现
    这里的trait字面意思是特质或者特征,这个词翻译成特征比较合适。它的意义和java,c#中接口很类似。但是trait支持部分实现,也就是说可以在scala的trait中可以实现部分方法。
    一般情况下Scala的类可以继承多个Trait,从结果来看就是实现了多重继承。Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait。
    继承的多个trait中如果有同名的方法和属性,必须要在类中使用“override”重新定义。
    trait中不可以传参数

    trait Read {
      val readType = "Read"
      val gender = "m"
      def read(name:String){
    	println(name+" is reading")
      }
    }
    
    trait Listen {
      val listenType = "Listen"
      val gender = "m"
      def listen(name:String){
    	println(name + " is listenning")
      }
    }
    
    class Person() extends Read with Listen{
      override val gender = "f"
    }
    
    object test {
      def main(args: Array[String]): Unit = {
        val person = new Person()
        person.read("zhangsan")
        person.listen("lisi")
        println(person.listenType)
        println(person.readType)
        println(person.gender)
        
      }
    }
    

    一下引用菜鸟教程的部分内容,原文摘录:

    /* 文件名:Test.scala
     * author:菜鸟教程
     * url:www.runoob.com
     */
    trait Equal {
      def isEqual(x: Any): Boolean
      def isNotEqual(x: Any): Boolean = !isEqual(x)
    }
    
    class Point(xc: Int, yc: Int) extends Equal {
      var x: Int = xc
      var y: Int = yc
      def isEqual(obj: Any) =
        obj.isInstanceOf[Point] &&
        obj.asInstanceOf[Point].x == x
    }
    
    object Test {
       def main(args: Array[String]) {
          val p1 = new Point(2, 3)
          val p2 = new Point(2, 4)
          val p3 = new Point(3, 3)
    
          println(p1.isNotEqual(p2))
          println(p1.isNotEqual(p3))
          println(p1.isNotEqual(2))
       }
    }
    

    执行结果为:

    false
    true
    true
    
  • 相关阅读:
    C
    如何让asp.net mvc 直接运行mobile页面
    Nuget找不到服务器
    C#调用R语言输出图片
    sql列转行
    C#读取注册表
    关于这个博客,关于我
    NOIP 2016 简要题解
    CSP2019 题解
    CF 练死劲
  • 原文地址:https://www.cnblogs.com/missedyou/p/13276747.html
Copyright © 2011-2022 走看看