scala面向对象

1.数组反转

object ExcuDemo {

  def swapArray(arr:Array[Int]) ={
    //这里只能使用until
    for (i <- 0 until arr.length-1 if(i%2==0)){
      arr(i) = arr(i)^arr(i+1)
      arr(i+1) = arr(i)^arr(i+1)
      arr(i) = arr(i)^arr(i+1)
    }
    arr
  }
  def main(args: Array[String]): Unit = {
    val arr = Array[Int](2,3,4,8,6,9,7,1,3)
    swapArray(arr).toList.foreach(x=>print(x+" "))
    //3 2 8 4 9 6 1 7 3

    println()
    //指定两个元素为一组
    val res: Iterator[Array[Int]] = arr.grouped(2)
    val res2: Iterator[Array[Int]] = res.map(x=>x.reverse)
    val res3: Iterator[Int] = res2.flatten
    while(res3.hasNext){
      print(res3.next()+" ")
      //3 2 8 4 9 6 1 7 3 
    }
  }
}

2.Key和value互换

import scala.collection.mutable.ListBuffer

object Text6 {
  def main(args: Array[String]): Unit = {
    /**
      * 6,key value互换
        val lst = List("Id1-The Spark","Id2-The Hadoop","Id3-The Spark")
        结果值:
            The-Id1 Id2 Id3
            Spark-Id1 Id3
            Hadoop-Id2
      */
    val lst = List("Id1-The Spark","Id2-The Hadoop","Id3-The Spark")
    //切割,组合
    val res: List[Array[(String,String)]] = lst.map({
      t =>
        val res1 = t.split("-")
        val key: String = res1(0)
        val values: Array[String] = res1(1).split(" ")
        val res2: Array[(String, String)] = values.map(x=>(x,key))
        res2
    })
    res.foreach(x=>print(x.toBuffer))
    //ArrayBuffer((The,Id1), (Spark,Id1))ArrayBuffer((The,Id2), (Hadoop,Id2))ArrayBuffer((The,Id3), (Spark,Id3))
    //压平
    println()
    val res2: List[(String, String)] = res.flatten
    res2.foreach(print)
    //(The,Id1)(Spark,Id1)(The,Id2)(Hadoop,Id2)(The,Id3)(Spark,Id3)
    //聚合
    println()
    val res3: Map[String, List[(String, String)]] = res2.groupBy(x => x._1)
    res3.foreach(print)
    //(Hadoop,List((Hadoop,Id2)))(Spark,List((Spark,Id1), (Spark,Id3)))(The,List((The,Id1), (The,Id2), (The,Id3)))
    //提取,组合
    println()
    val res4: Map[String, List[String]] = res3.mapValues({
      t=>
        t.map(x=>x._2)
    })
    res4.foreach(x=>print(x))
    //(Hadoop,List(Id2))(Spark,List(Id1, Id3))(The,List(Id1, Id2, Id3))
    println()
    val res5 = res4.map({
      t=>
        t._1.concat("-").concat(t._2.mkString(" "))
        //t._1.concat("-").concat(t._2.reduce(_+" "+_))
        //(t._1,t._2.reduce(_+" "+_))
    })
    res5.foreach(x=>println(x))
  }
}

3.交集,并集 差集——求平均温度

intersect  union  diff
object TempAvg {
  def main(args: Array[String]): Unit = {
    val d1 = Array(("bj",28.1), ("sh",28.7), ("gz",32.0), ("sz", 33.1))
    val d2 = Array(("bj",27.3), ("sh",30.1), ("gz",33.3))
    val d3 = Array(("bj",28.2), ("sh",29.1), ("gz",32.0), ("sz", 30.5))

    val res1 = d1.union(d2).union(d3)
    val res2 = d1.diff(d2).diff(d3)
    val res3 = d1.intersect(d1).intersect(d3)
    val res4 = d1 ++ d2 ++ d3
    println(res1.toMap)
    //Map(bj -> 28.2, sh -> 29.1, gz -> 32.0, sz -> 30.5)
    val stringToTuples: Map[String, Array[(String, Double)]] = res1.groupBy(x=>x._1)
    stringToTuples.foreach(x=>print(x._2.toBuffer))
    //ArrayBuffer((gz,32.0), (gz,33.3), (gz,32.0))ArrayBuffer((bj,28.1), (bj,27.3),
    // (bj,28.2))ArrayBuffer((sz,33.1), (sz,30.5))ArrayBuffer((sh,28.7), (sh,30.1), (sh,29.1))
    //第一种方式:
    println()
    val result = stringToTuples.map({
      x=>
        val city:String = x._1
        //获取相同城市的温度
        val temp: Array[Double] = x._2.map(x=>x._2)
        //求总温度
        val tempSum: Double = temp.sum
        val len = x._2.length
        //求平均温度
        val avg: Double = tempSum/len
        //返回结果
        (city,avg)
    })
    result.foreach(print)
    //(gz,32.43333333333333)(bj,27.86666666666667)(sz,31.8)(sh,29.3)

    //第二种方式:
    println()
    val values = stringToTuples.mapValues({
      arr=>
        //先求温度总和 用foldLeft
        val sumTamp = arr.foldLeft(0.0)((x,y)=>x+y._2)
        val length: Int = arr.length
        sumTamp/length
    })
    values.foreach(print)
    //(gz,32.43333333333333)(bj,27.86666666666667)(sz,31.8)(sh,29.3)

    val arr = List(List(3),List(2,5),List(7,9))
    //初始值必须有,运算中会被使用
    //aggregate的底层调用的还是foldLeft
    val d: Double = arr.aggregate(0.0)((x, y)=>x+y.sum,_+_)
    print(d)//26.0

    val arr1 = Array(1,2,3,4,5)
    print(arr1.aggregate(10)(_+_,_+_))//25
  }
}

4.面向对象
对象:object修饰
类:class修饰
类的实例:new class
1.对象
1)单例对象
Object修饰的对象不用static修饰,但是是静态的对象,称为单例对象

2)伴生对象
伴生对象是一种特殊的单例对象,需满足两个条件:
1.伴生对象和伴生类在同一个文件中
2.伴生对象名和伴生类名一样

这样的单例对象,被称作是这个类的伴生对象。类被称为是这个单例对象的伴生类。
结论:类和伴生对象之间可以相互访问私有的方法和属性

class Dog {
  val id = 1
  private var name = "xiaoqing"

  def printName(): Unit ={
    //在Dog类中可以访问伴生对象Dog的私有属性
    println(Dog.CONSTANT + name )
  }
}

/**
* 伴生对象
*/

object Dog {

  //伴生对象中的私有属性
  private val CONSTANT = "汪汪汪 : "

  def main(args: Array[String]) {
    val p = new Dog
    //访问私有的字段name
    p.name = "123"
    p.printName()
  }
}

3)Apply方法
Scala中的apply调用方法有两种:
1.在对象中调用;
对象名+方法名
2. 在类中调用
New class
类名+方法名
Object apply 主要用来解决复杂对象的初始化问题

class ApplyOperation {
}

class ApplyTest {
  def apply() = println("I spark so much!!!")

  def haveATry: Unit = {
    println("try again")
  }
}

object ApplyTest {
  def apply() = {
    println("I  am Scala")
  }
}

object ApplyOperation {
  def main(args: Array[String]) {
    val array = Array(1, 2, 3, 4)
    //这里ApplyTest.apply()中的()可以省略;但是ApplyTest()de ()
    //不能省略,shenglve后调用的是对象而不是类
    val test = new ApplyTest()
    val a = ApplyTest.apply //这里就是object中 apply 的使用
    val b = ApplyTest()
    val c = ApplyTest
    test.haveATry//try again// 这里就是 class 中 apply使用
    //a()// 这里就是 class 中 apply使用
    c.apply() //I  am Scala//这里就是object中 apply 的使用
  }
}

4)应用程序对象

object AppObjectDemo extends App{
  //不用写main方法
  println("I love you Scala")
}

App源码:内含main方法

trait App extends DelayedInit {

  /** The time when the execution of this program started, in milliseconds since 1
    * January 1970 UTC. */
  @deprecatedOverriding("executionStart should not be overridden", "2.11.0")
  val executionStart: Long = currentTime

  /** The command line arguments passed to the application's `main` method.
   */
  @deprecatedOverriding("args should not be overridden", "2.11.0")
  protected def args: Array[String] = _args

  private var _args: Array[String] = _

  private val initCode = new ListBuffer[() => Unit]

  /** The init hook. This saves all initialization code for execution within `main`.
   *  This method is normally never called directly from user code.
   *  Instead it is called as compiler-generated code for those classes and objects
   *  (but not traits) that inherit from the `DelayedInit` trait and that do not
   *  themselves define a `delayedInit` method.
   *  @param body the initialization code to be stored for later execution
   */
  @deprecated("The delayedInit mechanism will disappear.", "2.11.0")
  override def delayedInit(body: => Unit) {
    initCode += (() => body)
  }

  /** The main method.
   *  This stores all arguments so that they can be retrieved with `args`
   *  and then executes all initialization code segments in the order in which
   *  they were passed to `delayedInit`.
   *  @param args the arguments passed to the main method
   */
  @deprecatedOverriding("main should not be overridden", "2.11.0")
  def main(args: Array[String]) = {
    this._args = args
    for (proc <- initCode) proc()
    if (util.Properties.propIsSet("scala.time")) {
      val total = currentTime - executionStart
      Console.println("[total " + total + "ms]")
    }
  }
}

2.类
类和对象,应该怎么使用???
优先使用对象,如果需要构造器,那么只能使用类。
如果需要封装数据的时候,需要使用到类。
1) 类定义
在Scala中,类并不用声明为public。
Scala源文件中可以包含多个类,所有这些类都具有公有可见性。
var 修饰的变量, 这个变量对外提供getter setter方法
val 修饰的变量,是只读属性 对外提供了getter方法,没有setter(相当于java中用final修饰的变量)

class Student {

  val id = 666

    // _ 表示一个占位符, 编译器会根据变量的具体类型赋予相应初始值
    // 注意: 使用_ 占位符是, 变量类型必须指定
    var name: String = _

  //用var修饰的变量既有getter又有setter
  var age: Int = 20
}

object Test{
    val name: String = "zhangsan"
    def main(args: Array[String]): Unit = {

        // 调用空参构造器, 
        val student = new Student()
        student.name = "laowang"

        // 类中使用val修饰的变量不能更改
        // student.age = 20

        println(s"student.name ====== ${student.name} ${student.age}")
        println("Test.name ======" + Test.name)
    }
}

2)构造器
scala的构造器
主构造器和辅助构造器
创建对象的同时对属性赋值,初始化赋值
主构造器,和类的定义交织在一起,如果主构造器的变量使用了val或var修饰,变成了类的一个成员属性,如果有var或val修饰则成员属性可以在类和对象中被调用,反之只能在本class中调用
辅助构造器,def this(参数列表),
辅助构造器的第一行,必须调用其他的构造器(主,辅助。。。)
辅助构造器和主构造器的参数列表,不能完全一致,参数类型和个数一致。
如果想定义空参的辅助构造器,调用的主构造器的参数必须赋值(初始化)
作用域范围:
主: 类中除了属性和方法之外,都是构造器的作用域
辅助: 只在自己的方法范围之内

/**
  *每个类都有主构造器,主构造器的参数直接放置类名后面,与类交织在一起
  */
class Person(val name: String, val age: Int){
  //主构造器会执行类定义中的所有语句
  println("执行主构造器")

  private var gender = "male"

  //用this关键字定义辅助构造器
  def this(name: String, age: Int, gender: String){
    //每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
this(name, age)
    println("执行辅助构造器")
    this.gender = gender
  }
  var account1:String=_


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

    println("这里还是主构造器")

}

object Person {
    def main(args: Array[String]): Unit = {
        val s = new Person ("laoduan", 38)
        println(s"${s.name} ${s.age}")

        val s1 = new Person (“dingding", 18, "female")
        println(s"${s1.gender}")
val p2 =new Person("xx2",12,"female","9527")
println(s"${p2.age},${p2.account1}")
    }
}

3)访问权限
对于成员属性,成员方法,构造器(主构造器,赋值xxx):
默认的: public
private: 类和其伴生对象中有效,其他地方无效
private [this] : 只在类中有效
private [package] : 指定包及其子包内有效
对于主构造器,private写在构造器的前面

对于类:
默认的:public
private private[this]:在当前包及其子包范围内有效
private [package]: 在指定包及其子包范围内有效
[edu360.scala.day02] : package写法是错误的
[day02]:正确的,只需要一个包名就ok了。
面向对象的特性:封装 继承 多态

4)抽象类
对象本质上拥有类的所有特性,但是object没有构造器,必须是无参的。
在Scala中, 使用abstract修饰的类称为抽象类. 在抽象类中可以定义属性、未实现的方法(抽象方法)和具体实现的方法。

//抽象类

abstract class Animal1{
  //抽象字段
  var name:String
  var size:Int

  //抽象方法
  def walk
}

//抽象类实现类
class Cat(var length:Int)extends Animal1{
  override var name = "cat"
  override var size = 100
  override def walk{
    println(this.name + ":" + this.size + ":" + this.length)
  }

}
object AbstractClassTest {

  def main(args: Array[String]): Unit = {
    val cat = new Cat(200)
    println("name:" + cat.name)
    println("size:" + cat.size)
    println("length:" + cat.length)
    cat.walk
  }
}

3.特质
scala中没有interface implements
Trait(特质)相当于 java的接口。比接口功能更强大。特质中可以定义属性和方法的实现。
Scala的类只能够继承单一父类,但是可以实现(继承,混入)多个特质(Trait)使用的关键字是 with和extends
特质不能有任何的类参数,即传递给类的主构造器的参数。
比较:scala的trait和java中的interface的异同?
1,java的interface只定义方法名称和参数列表,不能定义方法体。而trait则可以定义方法体。
2,在java中实现接口用implements,而在scala中,实现trait用extends和with。
3,java的interface和scala的trait的最大区别是,scala可以在一个class实例化的时候动态混入trait。

用特质还是用抽象类??
1,优先使用特质。一个类可以扩展多个特质,但却只能扩展一个抽象类。
2,如果需要构造方法,使用抽象类。因为抽象类可以定义带参数的构造器,而特质不行。

trait T1 {
  // 定义普通方法,有方法实现
  def youcanfly()={
    println("tai feng lai le you can fly")
  }
}

trait T2 {
  // 定义一个属性
  val className: String = "NB大神班"

  // 定义一个没有实现的方法,默认就是抽象方法
  def teacherSay(name: String)

  // 定义带有具体的实现的方法
  def doSomething() = {
    println("群主开始发红包了...")
  }
  def teach(subject:String)
}

class Teacher{

}

object test{

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

    // 动态混入特征,让类有了特质的方法
    val t1 = new Teacher() with T1
    println(t1.youcanfly())

    // 动态混入特质不能使用extends关键字,可同时混入多个特质
    val t = new Teacher() with T1 with T2{
      // 如果特质中有抽象方法,则必须重写该抽象方法,可以不使用override关键字
      def teacherSay(name:String)={
        println(s"最高face,${name}")
      }
      // 重写一个有具体的实现的方法,必须使用关键字override
      override def doSomething() = {
        println("群主:抢到红包继续接龙...")
      }
      def teach(subject:String)={
        println(s"${subject}:抢到红包继续接龙...")
      }
    }
    println(t.teach("laozhao"))//laozhao:抢到红包继续接龙...
    println(t.doSomething)//群主:抢到红包继续接龙...
    println(t.youcanfly())//tai feng lai le you can fly
  }
}

4.继承
在继承抽象类或者特质的时候,继承抽象类使用extends,实现特质用with和extends,当类只实现了特质的时候,第一个关键字必须是extends
实现类还是特质,抽象方法都必须被实现,而且可以不使用override关键字
重写非抽象方法,必须使用override关键字
特质支持动态混入,在类实例化的时候,可以通过with关键字混入特质。
特质不能有构造器,抽象类可以有。

// 定义一个抽象类
abstract class Animal(val age: Int) {
  println("Animal`s main constructor invoked" + age)
  //定义一个抽象方法
  def run()
  def breath(): Unit = {
    println("呼吸氧气")
  }
}

// 定义一个特质,定义一个普通方法
trait Fightable {
  def fight(): Unit = {
    println("用嘴咬")
  }
}

// 定义一个特质,一个抽象方法
trait Flyable {
  // 定义一个抽象方法
  def fly()
}

//在scala中,不论是继承还是实现特质,第一个都用extends关键字
class Bird extends Flyable with Fightable {
  override def fly(): Unit = {
    println("用翅膀飞")
  }
}

object Bird {
  def main(args: Array[String]): Unit = {
    val b = new Bird
    b.fly()
  }
}

class Monkey(age: Int) extends Animal(age) with Flyable with Fightable {
  //重写抽象的方法, 可以不加override关键字
  def run(): Unit = {
    //    super()
    println("跳着跑")
  }

  //重写非抽象的方法,必须加override关键字
  override def breath(): Unit = {
    println("猴子呼吸")
  }

  override def fly(): Unit = {
    println("乘着筋斗云飞")
  }

  override def fight(): Unit = {
    println("用棒子打")
  }
  println("monkey`s main constructor invoked" + age)
}

object Monkey {
  def main(args: Array[String]): Unit = {
    val a: Animal = new Monkey(100)
    a.breath()
  }
}


5.模式匹配
1.样例类/样例对象
样例类:使用case关键字 修饰的类,重要的特征就是支持模式匹配,多例
样例object:使用case关键字修饰的对象,支持模式匹配,单例
case classclass的一些区别:
case class在初始化的时候,不用new,而普通类初始化时必须要newcase class 重写了toString方法。默认实现了equalshashCode实现了序列化接口
在Scala中样例类是一中特殊的类,可用于模式匹配。case class是多例的,case class 支持模式匹配(最重要的特征),所有case class 必须要有参数列表,有参数用case class,无参用case object
import scala.util.Random

case class SubmitTask(id: String, name: String)
case class HeartBeat(time: Long)
case object CheckTimeOutTask

object CaseDemo04 extends App{
  val arr = Array(CheckTimeOutTask, HeartBeat(12333), SubmitTask("0001", "task-0001"))

  arr(Random.nextInt(arr.length)) match {
    case SubmitTask(id, name) => {
      println(s"$id, $name")
    }
    case HeartBeat(time) => {
      println(time)
    }
    case CheckTimeOutTask => {
      println("check")
    }
  }
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值