Scala的Class、Object、Trait
开发环境
ideaIU或ideaIC。
idea的scala插件,File-Setting-Plugins,搜索scala在线安装,或下载后离线安装Install plugin from disk。
加载scala的包,Project Structure,Global Libraries,添加scala-sdk。
基础
scala中,break和continue的实现,
package com.padluo.spark.scala.basic
import scala.util.control.Breaks._
object BreakTest {
def main(args: Array[String]): Unit = {
// break
breakable {
for (i <- 1 to 10) {
if (i == 2) {
break()
}
println(i)
}
}
// continue
for (i <- 1 to 10) {
breakable {
if (i == 2) {
break()
}
println(i)
}
}
}
}
0 until 10
和0 to 10
的区别,until是0到9,相当于<,to是0到10,相当于<=。
scala用Java里面的类库,
package com.padluo.spark.scala.basic
import java.text.SimpleDateFormat
import java.util.{Calendar, Date}
object UseJava {
def main(args: Array[String]): Unit = {
val sdf:SimpleDateFormat = new SimpleDateFormat("yy-MM-dd")
val c = Calendar.getInstance()
println(c.getTime)
println(sdf.format(c.getTime))
// Convert Code from Java,可以直接把Java代码贴到scala文件中来
val sdf2: SimpleDateFormat = new SimpleDateFormat("yy-MM-dd")
sdf2.format(new Date)
}
}
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方法。
// TestVo.scala
package com.padluo.spark.scala.basic
import scala.beans.BeanProperty
class TestVo {
// class 里的属性默认是private类型,object里的属性默认是static
@BeanProperty var id = 10
@BeanProperty var name = null
@BeanProperty var addr = null
}
// TestVoMain.scala
package com.padluo.spark.scala.basic
object TestVoMain {
def main(args: Array[String]): Unit = {
var vo = new TestVo
println(vo.getId)
}
}
伴生对象
如何实现同个类既有普通方法又有静态方法?
伴生类和伴生对象可以相互访问彼此的私有成员。
package com.padluo.spark.scala.basic
class BanSheng {
def add2(a: Int, b: Int): Int = {
a + b
}
}
object BanSheng {
def add(a: Int, b: Int): Int = {
a + b
}
def main(args: Array[String]): Unit = {
BanSheng.add(1, 2) // 静态函数
val banSheng = new BanSheng
banSheng.add2(3, 4)
}
}
javap BanSheng.class反编译后,
public class com.padluo.spark.scala.basic.BanSheng {
public static void main(java.lang.String[]);
public static int add(int, int);
public int add2(int, int);
public com.padluo.spark.scala.basic.BanSheng();
}
伴生对象的apply方法,
package com.padluo.spark.scala.basic
class BanSheng(id: Int) {
def add2(a: Int, b: Int): Int = {
a + b
}
}
object BanSheng {
def apply(id: Int): BanSheng = {
println("----apply-----")
new BanSheng(id)
}
def add(a: Int, b: Int): Int = {
a + b
}
def main(args: Array[String]): Unit = {
BanSheng.add(1, 2) // 静态函数
val banSheng = new BanSheng(1)
banSheng.add2(3, 4)
val c = BanSheng(200)
val cc = BanSheng.apply(200)
}
}
单例模式,
package com.padluo.spark.scala.basic
class SingleTon {
}
object SingleTon {
private var s:SingleTon = null
def getInstance():SingleTon = {
if(s == null) {
new SingleTon()
} else {
s
}
}
def main(args: Array[String]): Unit = {
val singleTon = SingleTon.getInstance()
println(singleTon)
}
}
继承
- 继承关键词extends,多个用with。
- 某类如果不想被继承,可定义为final类型
- 用super调用父类的方法或属性
- 重写方法时必须用override,可以重写字段,不想被重写则定义为final类型
- 只有主构造器可以调父类的主构造器
Father.scala
package com.padluo.spark.scala.basic
class Father(name: String, age: Int) {
def doEat(food: String) {
println("eatting .." + food)
}
def printInfo2() {
println("name:" + name + ",age:" + age)
}
}
Son.scala
package com.padluo.spark.scala.basic
class Son(name: String, age: Int, addr: String) extends Father(name, age) {
// 子类把name和age传入到父类中
override def doEat(food: String) {
println("my eatting .." + food)
}
def printInfo() {
super.printInfo2()
println("name:" + name + ",age:" + age + ",addr:" + addr)
}
}
object Son {
def main(args: Array[String]): Unit = {
val s: Son = new Son("zhangsan", 30, "beijing")
s.printInfo()
}
}
Scala类层级结构,
Scala里,每个类都继承自通用的名为Any的超类。因为所有的类都是Any的子类,所以定义在Any中的方法就是“共同的”方法:它们可以被任何对象调用。
因为每个类都继承自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,
trait TestTrait {
def fun()
}
反编译后为
public interface com.padluo.spark.scala.basic.TestTrait {
public abstract void fun();
}
当def fun()改为def fun(){} 时,反编译结果如何?
trait TestTrait {
def fun() {}
}
反编译后为(有问题???)
D:\Java\idea\IdeaProjects\spark-study\spark-core\target\classes\com\padluo\spark\scala\basic>javap TestTrait.class
Compiled from "TestTrait.scala"
public abstract class com.padluo.spark.scala.basic.TestTrait$class {
public static void fun(com.padluo.spark.scala.basic.TestTrait);
public static void $init$(com.padluo.spark.scala.basic.TestTrait);
}
D:\Java\idea\IdeaProjects\spark-study\spark-core\target\classes\com\padluo\spark\scala\basic>javap TestTrait$class.class
Compiled from "TestTrait.scala"
public abstract class com.padluo.spark.scala.basic.TestTrait$class {
public static void fun(com.padluo.spark.scala.basic.TestTrait);
public static void $init$(com.padluo.spark.scala.basic.TestTrait);
}
案例2,
trait TestTrait {
def fun() {
println("---")
}
def fun200()
}
反编译后为(有问题)
D:\Java\idea\IdeaProjects\spark-study\spark-core\target\classes\com\padluo\spark\scala\basic>javap TestTrait.class
Compiled from "TestTrait.scala"
public abstract class com.padluo.spark.scala.basic.TestTrait$class {
public static void fun(com.padluo.spark.scala.basic.TestTrait);
public static void $init$(com.padluo.spark.scala.basic.TestTrait);
}
D:\Java\idea\IdeaProjects\spark-study\spark-core\target\classes\com\padluo\spark\scala\basic>javap TestTrait$class.class
Compiled from "TestTrait.scala"
public abstract class com.padluo.spark.scala.basic.TestTrait$class {
public static void fun(com.padluo.spark.scala.basic.TestTrait);
public static void $init$(com.padluo.spark.scala.basic.TestTrait);
本文首发于steem,感谢阅读,转载请注明。
微信公众号「padluo」,分享数据科学家的自我修养,既然遇见,不如一起成长。
读者交流电报群
知识星球交流群