2021-05-02

Scala day03

递归和尾递归

  1. 一个函数/方法在函数/方法体内又调用了本身,我们称之为递归调用
  2. 在递归的时候,只有递归,没有任何运算,这就是尾递归
  3. 阶乘
    递归算法
    1) 方法调用自身
    2) 方法必须要有跳出的逻辑
    3) 方法调用自身时,传递的参数应该有规律
    4) scala中的递归必须声明函数返回值类型
object TestFunction {

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

        println(test(5))
    }

    def test( i : Int ) : Int = {
        if ( i == 1 ) {
            1
        } else {
            i * test(i-1)
        }
    }
}

/**
  * guo chao
  * Date 2021/5/1
  */
object RecursiveDemo1 {
  def main(args: Array[String]): Unit = {
    println(factorial(3))
    println(factorial1(5,1))
  }
  //累加器 用来储存中间结果的
  @tailrec
  def factorial1(n:Int,acc:Int):Int={
    if(n==1 )  acc
    else factorial1(n-1,n * acc)
  }
  //计算阶乘
  def factorial(n:Long):Long={
    if (n==1) 1
    else n*factorial(n-1)
  }//可能栈溢出

}
/*
递归
1.找到递归的算法
2.在递归函数的内部,一定要有结束条件
3,随着递归的深入,要有机会到达结束条件
尾递归:
Scala会对尾递归做一个优化,尾递归优化,就不会出现StackOverflowError
*/

惰性求值

  1. 当函数返回值被声明为lazy时,函数的执行将被推迟,直到我们首次对此取值,该函数才会执行。这种函数我们称之为惰性函数。
  2. 案例实操
def main(args: Array[String]): Unit = {

    lazy val res = sum(10, 30)
    println("----------------")
    println("res=" + res)
}

def sum(n1: Int, n2: Int): Int = {
    println("sum被执行。。。")
    return n1 + n2
}

输出结果

----------------
sum被执行。。。
res=40

/**
  * guo chao
  * Date 2021/5/1
  */
object LazyDemo {
  val a1:Int={println("a1");10}//第一次使用a的时候才会求值
 lazy val a2:Int={println("a2");10}
  def a3:Int={println("a3");10}
  def main(args: Array[String]): Unit = {
    println(a1)//第一次,先判断a是否有值,如果没有则去计算,反之直接使用。
    println(a1)
    println(a1)
    
    println()
    println(a2)
    println(a2)
    println(a2)
    
    println()
    println(a3)
    println(a3)
    println(a3)
/*
惰性求值:
只能用val

主动求值:
系统一旦启动,所有的值都计算出来
好处:后面使用的时候速度快
坏处:拖慢系统的启动速度,浪费内存
*/

  }
}

面对对象

定义类
  1. 基本语法
    [修饰符] class 类名 {
    类体
    }
    说明
    (1)Scala语法中,类并不声明为public,所有这些类都具有公有可见性(即默认就是public)
    (2)一个Scala源文件可以包含多个类
  2. 案例实操
package com.atguigu.chapter07

//(1)Scala语法中,类并不声明为public,
//所有这些类都具有公有可见性(即默认就是public)
class Person {

}

//(2)一个Scala源文件可以包含多个类
class Teacher{

}
属性

属性是类的一个组成部分

  1. 基本语法
    [修饰符] var 属性名称 [:类型] = 属性值
    注:Bean属性(@BeanPropetry),可以自动生成规范的setXxx/getXxx方法
  2. 案例实操
package com.atguigu.scala.test

import scala.beans.BeanProperty

class Person {

  var name: String = "bobo" //定义属性

  var age: Int = _ // _表示给属性一个默认值

  //Bean属性(@BeanProperty)
  @BeanProperty var sex: String = "男"
}

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

    var person = new Person()
    println(person.name)

    person.setSex("女")
    println(person.getSex)
  }
}
/**
  * guo chao
  * Date 2021/5/1
  */
object objDemo1 {
  def main(args: Array[String]): Unit = {
    val user:User=new User()
    println(user.age)//    println(user.name)不能访问
    user.age=100
    println(user.age)
    user.eat()

  }
}
class User {
  //定义属性,和定义普通的变量完全一样
//@BeanProperty  var age: Int = 10
  @beanGetter  var age: Int = 10
   private var name: String = "lisi"

 
  def eat(): Unit = { //给类定义方法
    println("eat:" + name)
  }
}

构造器
  1. 基本语法
    class 类名(形参列表) { // 主构造器
    // 类体
    def this(形参列表) { // 辅助构造器
    }
    def this(形参列表) { //辅助构造器可以有多个…
    }
    }
    说明:
    (1)辅助构造器,函数的名称this,可以有多个,编译器通过参数的个数来区分。
    (2)辅助构造方法不能直接构建对象,必须直接或者间接调用主构造方法。
  2. 案例实操
    (1)如果主构造器无参数,小括号可省略,构建对象时调用的构造方法的小括号也可以省略。
    //(1)如果主构造器无参数,小括号可省略
    //class Person (){
class Person {

  var name: String = _

  var age: Int = _

  def this(age: Int) {
    this()
    this.age = age
    println("辅助构造器")
  }

  def this(age: Int, name: String) {
    this(age)
    this.name = name
  }

  println("主构造器")
}

object Person {

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

    val person2 = new Person(18)
  }
}
构造器参数
  1. 说明
    Scala类的主构造器函数的形参包括三种类型:未用任何修饰、var修饰、val修饰
    (1)未用任何修饰符修饰,这个参数就是一个局部变量
    (2)var修饰参数,作为类的成员属性使用,可以修改
    (3)val修饰参数,作为类只读属性使用,不能修改

  2. 案例实操
    class Person(name: String, var age: Int, val sex: String) {

}

object Test {

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

    var person = new Person("bobo", 18, "男")

    // (1)未用任何修饰符修饰,这个参数就是一个局部变量
    // printf(person.name)

    // (2)var修饰参数,作为类的成员属性使用,可以修改
    person.age = 19
    println(person.age)

    // (3)val修饰参数,作为类的只读属性使用,不能修改
    // person.sex = "女"
    println(person.sex)
  }
}
/**
  * guo chao
  * Date 2021/5/1
  */
object obj3 {
  def main(args: Array[String]): Unit = {
    val chengwei:User3=new User3(10,"chengwei","male")
    println(chengwei.age)
//给类起别名
    type U=User3
    val u:U=new User3(10,"a","female")
    println(u.age)
    println(u.getClass.getName)
  }
}
class User3(val age:Int,var name:String,sex:String){

    //这种构造器:辅构造器
    def this(){
      this(10,"abc","male") //首行必须是调用主构造器
    }
    def this(c:Int){
      this(10,"abc","male")//构造器内调用构造器
      println(c)
    }
  def eat={
    println(sex)
    println(this.age)//站在面向
  }
}

导包

Scala中也有包,包的命名使用规则和Java一样
包的声明
1)package com.syf.scala1015day03.pack
2)包语句
在Scala中,一个.Scala文件中一般会写多个类,所有的类会默认在一个包里
package aa{
class A
}
2.包的使用
如果导包和导类
1)在文件的最顶层导
import java.util.HashMap
2)在代码的任何需要的地方导包
比如可以在方法的内部
3)通配符导入
import java.util._
import java.util.{TreeMap,HashMap}
//导包的时候给类起别名
import java.util.{HashMap=>jHashMap}
//不想用HashMap,其他的都想用
import java.util.{HashMap=>,}

import java.util.HashMap
package com.syf.scala1015day03.pack
//不想用HashMap,其他的都想用
import java.util.{HashMap=>_,_}
import java.util.{TreeMap,HashMap}
//导包的时候给类起别名
import java.util.{HashMap=>jHashMap}
/**
  * guo chao
  * Date 2021/5/1
  */
object Pack1 {
  def main(args: Array[String]): Unit = {

//    new util.HashMap[String,String]()

  }
}
class A{
//  new util.HashMap[]()
}
package aa{
  class A
}

权限修饰符

在Java中,访问权限分为:public,private,protected和默认。在Scala中,你可以通过类似的修饰符达到同样的效果。但是使用上有区别。
(1)scala 中属性和方法的默认访问权限为public,但scala中无public关键字。
(2)private为私有权限,只在类的内部和伴生对象中可用。
(3)protected为受保护权限,Scala中受保护权限比Java中更严格,同类、子类可以访问,同包无法访问。
(4)private[包名]增加包访问权限,包名下的其他类也可以使用

继承

  1. 基本语法
    class 子类名 extends 父类名 { 类体 }
    (1)子类继承父类的属性和方法
    (2)scala是单继承
  2. 案例实操
    (1)子类继承父类的属性和方法
    (2)继承的调用顺序:父类构造器->子类构造器
class Person(nameParam: String) {

  var name = nameParam
  var age: Int = _

  def this(nameParam: String, ageParam: Int) {
    this(nameParam)
    this.age = ageParam
    println("父类辅助构造器")
  }

  println("父类主构造器")
}


class Emp(nameParam: String, ageParam: Int) extends Person(nameParam, ageParam) {

  var empNo: Int = _

  def this(nameParam: String, ageParam: Int, empNoParam: Int) {
    this(nameParam, ageParam)
    this.empNo = empNoParam
    println("子类的辅助构造器")
  }

  println("子类主构造器")
}

object Test {
  def main(args: Array[String]): Unit = {
    new Emp("z3", 11,1001)
  }
}
/**
  * guo chao
  * Date 2021/5/1
  */
class Extends1 {
  def main(args: Array[String]): Unit = {
    val  b:B=new B
    b.foo()
  }
}
class A(val a:Int){
  println("A 主构造内的代码")
  def foo()={
    println("A foo...")
  }

}
class B (val b:Int)extends A(b){
  override def foo(): Unit = {
    println("B foo...")
  }
}

抽象类

定义抽象类:abstract class Person{} //通过abstract关键字标记抽象类

/**
  * guo chao
  * Date 2021/5/1
  */
object abs1 {
  def main(args: Array[String]): Unit = {
//    val b:B=new B
//    b.foo()
    val a:A=new A(20){
      var b:Int=30
      def foo:Int= {
        println("abc")
        100
      }
      }
    a.foo()
    }

}
abstract class A(var a:Int){
  var b:Int //属性只声明,不初始化,这就是抽象字段
  def foo():Int//方法只声明,没有实现,就是抽象方法
}
class B extends A(20){
  override var b: Int = _

  override def foo(): Int = {
    println("foo...")
  }
}

单例对象及伴生对象

  1. 基本语法
    object Person{
    val country:String=“China”
    }
  2. 说明
    (1)单例对象采用object关键字声明
    (2)单例对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。
    (3)单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。
  3. 案例实操
//(1)伴生对象采用object关键字声明
object Person {
  var country: String = "China"
}

//(2)伴生对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。
class Person {
  var name: String = "bobo"
}

object Test {
  def main(args: Array[String]): Unit = {
    //(3)伴生对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。
    println(Person.country)
  }
}
/**
  * guo chao
  * Date 2021/5/1
  */
object Single1 {
  def main(args: Array[String]): Unit = {
    A.foo
    A()//相当于A.apply()
    a()//相当于a.apply()
    val a:A=new A
  }
}
object A{
  def foo= println("foo...")

  def apply(): Int = {
    println("apply")
    10
  }
}
class A{
  def apply()={
    println("class A apply....")
  }
}
/*
单例对象:
Java实现单例:
1.饿汉式
2.懒汉式
scala中单例:
使用object关键字,声明出来的对象就是一个单例对象
独立对象
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值