2-函数

1. scala class与object二次理解(函数定义上理解)

使用上理解为,object中的方法,在其他地方可以通过类名.方法的方式使用,可以认为object中的方法,都是静态方法。但是,实际上是,他们都是普通方法,这些object中的方法,其实是伴生类中的实例方法,之所以可以通过类名.方法,则是因为伴生类中有个静态实例,外部调用这些方法,编译的时候,是编译成获取到静态实例,然后通过静态实例去调用方法。

在伴生类中,定义的方法,则里面的方法,是在object名字对应的class中,这个class才是最终使用的。总之,是object和class共同组成了一个完整的类object同名,这个类中静态方法,有普通方法等。外部使用静态方法,在是object生成的伴生类提供作用。

package cn.chapter3_function

/**
 * 1.函数定义的方式:
 * scala的设计者任务static静态方法不符合面向对象的方式,所以在底层上,把这种替换static方法
 * 全部都生成了伴生类中的普通方法,在object中定义的方法,可以使用类名.方法去定义,但是,实际上
 * 是符合面向对象的,因为,把所有的object的中的方法,都是在伴生类中定义的,调用方式也是通过一个
 * 静态对象去实现的调用伴生类内部的方法,本质上还是对象之间的方法调用,而不是静态之间的调用。
 *2.伴生类与伴生对象二次理解:
 * Fun1_def.funcName2("s") //funcName2定义在object中
 * new Fun1_def().funcName("ss") //定义在class中
 *
 * //反编译之后
 * Fun1_def$.MODULE$.funcName2("s"); object的方法,通过伴生类的实例对象用
 * new Fun1_def().funcName("ss");  class的方法,通过new object的class实现。
 * 2.1:Object中定义的方法,编译之后,全部在伴生类中间实现,外部直接类名.方法名(funcName2d在object中)调用,
 * 则是通过Fun1_def$.MODULE$.funcName2("s");本质上,还是使用伴生类实例的方法。
 * 2.2:object才是大头,在class中的方法,都是在object中创建的,使用对象也是object new出来的,伴生类就是用来
 * 存储object中的静态方法的,其余的没什么用处了。以后使用的时候,就创建一个object,在他的class下,写语句,这些
 * 语句最终属于object。
 * 2.3: 这样做的好处是,static方法不存在了,都是普通的方法,方法的调用都是通过实例实现的。
 *
 */
class Fun1_def {

  def funcName(param1: String): Int = {
    println("class定义函数:输出函数参数值" + param1)
    return 1
  }

}

object Fun1_def {

  def main(args: Array[String]): Unit = {
    //2.定义在这个位置的函数,是伴生类定义的私有方法,函数名是$1,在原有基础之上。
    def funcName(param1: String): Int = {
      println("object中main方法中:输出函数参数值2" + param1)
      return 1
    }

    val fun1_def = new Fun1_def()
    fun1_def.funcName("zs")
    funcName2("name")
  }

  //1.通用格式,定义在object的函数,就是静态方法,直接类型.方法名都可以调用了。
  def funcName2(param1: String): Int = {
    println("object定义函数:输出函数参数值" + param1)
    return 1
  }
}

2. 方法的定义与返回值
def 方法名(参数名 : 参数类型, .... ) : 返回类型 = { 方法体 }

对于返回值,可以不写返回类型,会自动推断出来。如果返回Unit,则可以不用写=。

package cn.chapter3_function

/**
 * 方法返回值。记住返回Unit三种函数声明
 */
object Fun2_return {

  def main(args: Array[String]): Unit = {

  }

  //1. 单行函数,可以不加大括号
  def fun1() = println()

  //2.当不添加函数返回值时,会自动进行类型推导,如果不加=,则无返回值
  def fun2() = {
    ""
  }

  //对于函数的返回值为Unit的时候,即不需要函数返回值的时候,称为过程:
  def fun3(): Unit = {
    println("过程函数定义1: 返回值为Unit")
  }

  def fun4() = {
    println("过程函数定义2: 不写返回值,也不返回任何数值")
  }

  def fun5() {
    println("过程函数定义3: 不写=号,则默认的返回值就是Unit")
  }

}

3. 函数参数
  • 默认参数,在类型后添加默认值,调用时,可以不用写。
  • 带名参数,定义了多个默认参数,可以通过参数名单独指定某个参数的值。
  • **问题:**如果定义一个含有默认参数方法,和该函数的重载方法冲突了,则优先使用重载方法。 def fun1(){} 和 def fun1(name : String='zs').
  • 可变参数: 在参数类型后添加 *, 实现原理是,参数的类型是seq[String]。
  • 序列如何在可变参数中使用,格式 `seq(1,2,3): _* .
package cn.chapter3_function

/**
 * 函数3: 参数值
 * 1.默认参数,在参数的类型加上默认参数值,调用可以不用填写参数值。
 * 如果给出的参数不够,则会从左到右依次应用参数。
 * 2.带名参数:如果有多个默认参数,则通过指定参数名的方式赋值。
 * 3.如果含有方法重载,和方法默认值冲突,则优先调用重载的方法。
 * 4.可变参数的定义,在类型上添加*,本质原理是参数类型是序列。
 * 5.对于一个可变参数,如果序列向传入当参数,需要将序列单独遍历出来,当参数传进去。
 *  seq : _* 这种操作。(反编译看不懂实现原理)
 */
object Fun3_param {
  def main(args: Array[String]): Unit = {
    fun1("zs", 29)

    /* 最终对于默认参数的调用方式。
    int x$1 = 19;
    String x$2 = fun2$default$1();
    fun2(x$2, x$1);
     public int fun1$default$2()
     {
       return 10;
     }
     */
    fun2(age = 19)

    //fun2方法有两个,使用这个参数,可以符合fun2(name,age)参数有默认值,和fun2(name),这个
    //则会优先匹配参数个数匹配的方法。
    fun2("zs")

    //4.定义了可变参数,使用普通参数调用。
    val zs: Int = fun3("zs", "ls", "ww")
    println("fun3结果返回值" + zs)

    //5.对于可变参数函数,参数类型不能是序列类型。因为接受和传递的参数类型都是不一致的。可以
    //将序列的值遍历出来,一个个传入进去
    fun3(Seq[String]("zs2", "ls2", "ww2"): _*)
  }

  //1.函数使用默认参数,可以在调用的时候,不指定这个参数的值。
  def fun1(name: String, age: Int = 10): Unit = {
    println(s"姓名是${name},age是${age}")
  }

  //2.函数中含有多个默认参数,如果想给单独参数赋值,通过属性名指定。
  def fun2(name: String = "zs", age: Int = 10): Unit = {
    println(s"姓名是${name},age是${age}")
  }

  //3.方法重载时,如果有默认参数,如何区分。会优先使用重载函数u.
  def fun2(name: String): Unit = {
    println(s"姓名是${name}")
  }

  //4.定义可变参数,在方法名的类型上添加*,同样可变参数必须在最后。
  //public int fun3(Seq<String> name),原理和java一样,都是数组,这个是序列。可以对参数进行序列的操作。
  def fun3(name: String*): Int = {
    for (s <- name) {
      println(s)
    }
    name.length
  }
}

4. 案例 (定义可变参数函数,使用递归实现求和)
package cn.chapter3_function

/**
 * 函数案例:递归实现序列累加
 */
object Fun4_example {

  def main(args: Array[String]): Unit = {
    val i: Int = sum(1, 2, 3)
    println(i)
  }

  /**
   * 定义一个函数,递归实现序列累加:
   * 第一个值,加上后面所有尾巴的值。
   * seq.tail: 截取序列,除了第一个值。
   *
   * @param seq
   * @return
   */
  def sum(seq: Int*): Int = {
    if (seq.length == 0) {
      0
    } else {
      seq.head + sum(seq.tail: _*)
    }
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值