Scala的Class、Object、Trait

前提是你 提交于 2020-03-08 16:42:36

开发环境

ideaIU或ideaIC。

idea的scala插件,File-Setting-Plugins,搜索scala在线安装,或下载后离线安装Install plugin from disk。

加载scala的包,Project Structure,Global Libraries,添加scala-sdk。

基础

scala中,break和continue的实现

 1package com.padluo.spark.scala.basic
 2import scala.util.control.Breaks._
 3object BreakTest {
 4  def main(args: Array[String]): Unit = {
 5    // break
 6    breakable {
 7      for (i <- 1 to 10) {
 8        if (i == 2) {
 9          break()
10        }
11        println(i)
12      }
13    }
14    // continue
15    for (i <- 1 to 10) {
16      breakable {
17        if (i == 2) {
18          break()
19        }
20        println(i)
21      }
22    }
23  }
24}

0 until 100 to 10的区别,until是0到9,相当于<,to是0到10,相当于<=。

scala用Java里面的类库

 1package com.padluo.spark.scala.basic
 2import java.text.SimpleDateFormat
 3import java.util.{Calendar, Date}
 4object UseJava {
 5  def main(args: Array[String]): Unit = {
 6    val sdf:SimpleDateFormat = new SimpleDateFormat("yy-MM-dd")
 7    val c = Calendar.getInstance()
 8    println(c.getTime)
 9    println(sdf.format(c.getTime))
10    // Convert Code from Java,可以直接把Java代码贴到scala文件中来
11    val sdf2: SimpleDateFormat = new SimpleDateFormat("yy-MM-dd")
12    sdf2.format(new Date)
13  }
14}

Class、Object、Trait

类class里无static类型,类里的属性和方法,必须通过new出来的对象来调用,所以有main主函数也没用。

而object的特点是:

  • 可以拥有属性和方法,且默认都是"static"类型,可以直接用object名直接调用属性和方法,不需要通过new出来的对象(也不支持)。
  • object里的main函数式应用程序的入口。
  • object和class有很多和class相同的地方,可以extends父类或Trait,但object不可以extends object,即object无法作为父类。

构造函数

  • 一个主构造器(函数),其他是辅助构造器
  • 辅助构造器的实现体里,必须引用(调用)主构造器
  • 主构造器的参数,也会成为类的属性(?正确吗?)
  • 辅助构造函数的名称都是this
  • 辅助构造函数中必须以一个其他辅助构造器或主构造器的调用开始

Bean属性,定义getter和settet方法。

 1// TestVo.scala
 2package com.padluo.spark.scala.basic
 3import scala.beans.BeanProperty
 4class TestVo {
 5  // class 里的属性默认是private类型,object里的属性默认是static
 6  @BeanProperty var id = 10
 7  @BeanProperty var name = null
 8  @BeanProperty var addr = null
 9}
10// TestVoMain.scala
11package com.padluo.spark.scala.basic
12object TestVoMain {
13  def main(args: Array[String]): Unit = {
14    var vo = new TestVo
15    println(vo.getId)
16  }
17}

伴生对象

如何实现同个类既有普通方法又有静态方法?

伴生类和伴生对象可以相互访问彼此的私有成员。

 1package com.padluo.spark.scala.basic
 2class BanSheng {
 3  def add2(a: Int, b: Int): Int = {
 4    a + b
 5  }
 6}
 7object BanSheng {
 8  def add(a: Int, b: Int): Int = {
 9    a + b
10  }
11  def main(args: Array[String]): Unit = {
12    BanSheng.add(1, 2) // 静态函数
13    val banSheng = new BanSheng
14    banSheng.add2(3, 4)
15  }
16}

javap BanSheng.class反编译后,

1public class com.padluo.spark.scala.basic.BanSheng {
2  public static void main(java.lang.String[]);
3  public static int add(int, int);
4  public int add2(int, int);
5  public com.padluo.spark.scala.basic.BanSheng();
6}

伴生对象的apply方法

 1package com.padluo.spark.scala.basic
 2class BanSheng(id: Int) {
 3  def add2(a: Int, b: Int): Int = {
 4    a + b
 5  }
 6}
 7object BanSheng {
 8  def apply(id: Int): BanSheng = {
 9    println("----apply-----")
10    new BanSheng(id)
11  }
12  def add(a: Int, b: Int): Int = {
13    a + b
14  }
15  def main(args: Array[String]): Unit = {
16    BanSheng.add(1, 2) // 静态函数
17    val banSheng = new BanSheng(1)
18    banSheng.add2(3, 4)
19    val c = BanSheng(200)
20    val cc = BanSheng.apply(200)
21  }
22}

单例模式

 1package com.padluo.spark.scala.basic
 2class SingleTon {
 3}
 4object SingleTon {
 5  private var s:SingleTon = null
 6  def  getInstance():SingleTon = {
 7    if(s == null) {
 8      new SingleTon()
 9    } else {
10      s
11    }
12  }
13  def main(args: Array[String]): Unit = {
14    val singleTon = SingleTon.getInstance()
15    println(singleTon)
16  }
17}

继承

  • 继承关键词extends,多个用with。
  • 某类如果不想被继承,可定义为final类型
  • 用super调用父类的方法或属性
  • 重写方法时必须用override,可以重写字段,不想被重写则定义为final类型
  • 只有主构造器可以调父类的主构造器

Father.scala

1package com.padluo.spark.scala.basic
2class Father(name: String, age: Int) {
3  def doEat(food: String) {
4    println("eatting .." + food)
5  }
6  def printInfo2() {
7    println("name:" + name + ",age:" + age)
8  }
9}

Son.scala

 1package com.padluo.spark.scala.basic
 2class Son(name: String, age: Int, addr: String) extends Father(name, age) {
 3  // 子类把name和age传入到父类中
 4  override def doEat(food: String) {
 5    println("my eatting .." + food)
 6  }
 7  def printInfo() {
 8    super.printInfo2()
 9    println("name:" + name + ",age:" + age + ",addr:" + addr)
10  }
11}
12object Son {
13  def main(args: Array[String]): Unit = {
14    val s: Son = new Son("zhangsan", 30, "beijing")
15    s.printInfo()
16  }
17}

Scala类层级结构

Scala里,每个类都继承自通用的名为Any的超类。因为所有的类都是Any的子类,所以定义在Any中的方法就是“共同的”方法:它们可以被任何对象调用。

Scala类层级结构Scala类层级结构

因为每个类都继承自Any,所以Scala程序里的每个对象都能用==、!=或equals比较,用hashCode做散列,以及用toString转为字符串。Any类里的等号和不等号方法被声明为final,因此他们不能再子类里重写。实际上,==总是与equals相同,!=总是与equeal相反。因此,独立的类可以通过重写equals方法改变==!=的意义。

Any有两个子类:AnyVal和AnyRef(相当于Java里的Object)。
AnyVal是Scala里每个内建值类的父类。有9个这样的值类:Byte、Short、Char、Int、Long、Float、Double、Boolean和Unit。其中的前8个都对应到Java的基本类型。这些值类都被定义为既是抽象的又是final的,不能使用new创造这些类的实例。Unit被用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()。

AnyRef类是Scala里所有引用类(reference class)的基类。它其实是Java平台上java.lang.Object类的别名。因此Java里写的类和Scala里写的都继承自AnyRef。

Scala类与Java类的不同在于它们还继承自一个名为ScalaObject的特别trait。是想要通过ScalaObject包含的Scala编译器定义和实现的方法让Scala程序的执行更高效。

scala.Null和scala.Nothing是用统一的方式处理Scala面向对象类型系统的某些“边界情况”的特殊类型。Null类是null引用对象的类型,它是每个引用类(继承自AnyRef的类)的子类。Null不兼容值类型。Nothing类型在Scala的类层级的最低端;它是任何其他类型的子类型。然而,根本没有这个类型的任何值。Nothing的一个用处是它标明了不正常的终止。

Trait特质

为什么不可以继承多个父类?原因是多个父类里有相同函数或属性时,无法控制用哪个。

Scala的Trait相当于Java里的Interface,但Trait不仅可以定义函数,还可以有函数体实现。实现关键词是extends,实现多个Trait用with。当extends的多个Trait里有相同函数时,子类必须重写该函数。

  • 父trait里无函数体的函数,子类必须override
  • 重写父类里有函数体的函数,必须有关键词override
  • trait里的变量,都是val类型
  • 在trait里定义的的变量,必须是val类型,如果变量没初始化,子类必须override

案例1,

1trait TestTrait {
2  def fun()
3}

反编译后为

1public interface com.padluo.spark.scala.basic.TestTrait {
2  public abstract void fun();
3}

当def fun()改为def fun(){} 时,反编译结果如何?

1trait TestTrait {
2  def fun() {}
3}

反编译后为(有问题???)

 1D:\Java\idea\IdeaProjects\spark-study\spark-core\target\classes\com\padluo\spark\scala\basic>javap TestTrait.class
 2Compiled from "TestTrait.scala"
 3public abstract class com.padluo.spark.scala.basic.TestTrait$class {
 4  public static void fun(com.padluo.spark.scala.basic.TestTrait);
 5  public static void $init$(com.padluo.spark.scala.basic.TestTrait);
 6}
 7D:\Java\idea\IdeaProjects\spark-study\spark-core\target\classes\com\padluo\spark\scala\basic>javap TestTrait$class.class
 8Compiled from "TestTrait.scala"
 9public abstract class com.padluo.spark.scala.basic.TestTrait$class {
10  public static void fun(com.padluo.spark.scala.basic.TestTrait);
11  public static void $init$(com.padluo.spark.scala.basic.TestTrait);
12}

案例2,

1trait TestTrait {
2  def fun() {
3    println("---")
4  }
5  def fun200()
6}

反编译后为(有问题)

 1D:\Java\idea\IdeaProjects\spark-study\spark-core\target\classes\com\padluo\spark\scala\basic>javap TestTrait.class
 2Compiled from "TestTrait.scala"
 3public abstract class com.padluo.spark.scala.basic.TestTrait$class {
 4  public static void fun(com.padluo.spark.scala.basic.TestTrait);
 5  public static void $init$(com.padluo.spark.scala.basic.TestTrait);
 6}
 7D:\Java\idea\IdeaProjects\spark-study\spark-core\target\classes\com\padluo\spark\scala\basic>javap TestTrait$class.class
 8Compiled from "TestTrait.scala"
 9public abstract class com.padluo.spark.scala.basic.TestTrait$class {
10  public static void fun(com.padluo.spark.scala.basic.TestTrait);
11  public static void $init$(com.padluo.spark.scala.basic.TestTrait);

本文首发于steem,感谢阅读,转载请注明。

https://steemit.com/@padluo


微信公众号「padluo」,分享数据科学家的自我修养,既然遇见,不如一起成长。

数据分析数据分析


读者交流电报群

https://t.me/sspadluo


知识星球交流群

知识星球读者交流群知识星球读者交流群

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!