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」,分享数据科学家的自我修养,既然遇见,不如一起成长。
读者交流电报群
知识星球交流群
Leave Scala的Class、Object、Trait to:
Read more #cn posts
Best Posts From padluo
We have not curated any of padluo's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.