Scala: 类

本文深入探讨Scala类的定义、域、方法、构造器、case类、类继承、Trait等核心特性,以及如何在实际编程中应用这些概念。

class

Scala类使用class关键字定义,是对象的模板或者蓝图:

  class Calculator {
    val brand: String = "HP"
    def add(m: Int, n: Int): Int = m + n
  }

  val calc = new Calculator                       //> 
  calc.add(3, 2)                                  //> res0: Int = 5
  calc.brand                                      //> res1: String = HP

上例中使用val定义类的域,使用def定义类的方法,方法只是可以访问类实例状态的函数。

Methods are just functions that can access the state of the class.

构造器

不像Java中有特殊的构造方法,scala没有,在类中,方法定义之外的代码就是构造器,用于初始化对象的状态。

class Calculator(brand: String) {
  /**
   * A constructor.
   */
  val color: String = if (brand == "TI") {
    "blue"
  } else if (brand == "HP") {
    "black"
  } else {
    "white"
  }

  // An instance method.
  def add(m: Int, n: Int): Int = m + n
}

构造器的参数在类名后面定义,使用new关键字创建类的实例:

 val calc = new Calculator("HP")
 calc.color

case class

case类是一种特殊的类,用于match的模式匹配,实例化时不需要使用new关键字。

case class Status(status:String)

val s1 = Status("Finish")
val s2 = Status("Running")

类继承

class ScientificCalculator(brand: String) extends Calculator(brand) {
  def log(m: Double, base: Double) = math.log(m) / math.log(base)
}

覆盖基类方法:

class EvenMoreScientificCalculator(brand: String) extends ScientificCalculator(brand) {
  def log(m: Int): Double = log(m, math.exp(1))
}

如果只想在类中定义方法,不提供实现,使用抽象类:

  abstract class Shape {
    def getArea(): Int // subclass should define this
  }

  class Circle(r: Int) extends Shape {
    def getArea(): Int = { r * r * 3 }
  }

抽象类不能被实例化。

Trait

特质Trait定义一组域和方法,可以被扩展或者混入到类中。

traits are collections of fields and behaviors that you can extend or mixin to your classes.

Trait类似与Java中的接口,但是Trait可以提供方法实现,更像是Java中的抽象类,但是类可以同时混入多个Trait(而Java只支持单继承)。

trait Car {
  val brand: String
}

trait Shiny {
  val shineRefraction: Int
}

扩展Trait:

class BMW extends Car {
  val brand = "BMW"
}

使用with扩展多个trait:

class BMW extends Car with Shiny {
  val brand = "BMW"
  val shineRefraction = 12
}

多个with:


  trait Shap {
    val af: Int
  }

  class BMW extends Car with Shiny with Shap {
    val brand = "BMW"
    val shineRefraction = 12
    val af = 9
  }

一般,with被成为混入(mixin),而不是继承或扩展。另外,可以在实例化的时候才混入Trait:

  class BMW extends Car with Shiny {
    val brand = "BMW"
    val shineRefraction = 12

  }

 val bmw =  new BMW with Shap{
    val af = 10
  }    

Trait or 抽象类:

两者的选择有时候很难,但是有一些经验可以供参考:
- 尽量使用trait,因为一个类只能集成一个class,但是可以mixin多个trait
- 如果需要构造参数,只能使用抽象类,因为trait的构造函数不能接收参数。

可以参考一下一些文章:
1) stackoverflow:Scala traits vs abstract classes
2) Difference between Abstract Class and Trait
3) Programming in Scala: To trait, or not to trait?

Types 泛型

scala中的泛型(Java中的说法)使用[]来表达,类似与Java的<>。

泛型类

trait Cache[K, V] {
  def get(key: K): V
  def put(key: K, value: V)
  def delete(key: K)
}

泛型方法

在方法名后面使用[]表示(Java中在方法名之前使用<>表示)

def remove[K](key: K)
scala: ## Exception when compiling 3 sources to D:\MAVEN\IDEAproject\flink_project\target\classes java.lang.IllegalArgumentException: 无效的标记: -proc:full com.sun.tools.javac.api.JavacTool.processOptions(JavacTool.java:206) com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:156) com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:107) com.sun.tools.javac.api.JavacTool.getTask(JavacTool.java:64) sbt.internal.inc.javac.LocalJavaCompiler.run(LocalJava.scala:343) sbt.internal.inc.javac.AnalyzingJavaCompiler.$anonfun$compile$12(AnalyzingJavaCompiler.scala:172) scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18) sbt.internal.inc.javac.AnalyzingJavaCompiler.timed(AnalyzingJavaCompiler.scala:262) sbt.internal.inc.javac.AnalyzingJavaCompiler.compile(AnalyzingJavaCompiler.scala:161) sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compileJava$2(MixedAnalyzingCompiler.scala:104) sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compileJava$2$adapted(MixedAnalyzingCompiler.scala:92) sbt.internal.inc.JarUtils$.withPreviousJar(JarUtils.scala:241) sbt.internal.inc.MixedAnalyzingCompiler.$anonfun$compileJava$1(MixedAnalyzingCompiler.scala:92) scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.scala:18) sbt.internal.inc.MixedAnalyzingCompiler.timed(MixedAnalyzingCompiler.scala:252) sbt.internal.inc.MixedAnalyzingCompiler.compileJava(MixedAnalyzingCompiler.scala:61) sbt.internal.inc.MixedAnalyzingCompiler.compileJava0$1(MixedAnalyzingCompiler.scala:201) sbt.internal.inc.MixedAnalyzingCompiler.compile(MixedAnalyzingCompiler.scala:214) sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1(IncrementalCompilerImpl.scala:542) sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileInternal$1$adapted(IncrementalCompilerImpl.scala:542) sbt.internal.inc.Incremental$.$anonfun$apply$3(Incremental.scala:178) sbt.internal.inc.Incremental$.$anonfun$apply$3$adapted(Incremental.scala:176) sbt.internal.inc.Incremental$$anon$2.run(Incremental.scala:454) sbt.internal.inc.IncrementalCommon$CycleState.next(IncrementalCommon.scala:117) sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:56) sbt.internal.inc.IncrementalCommon$$anon$1.next(IncrementalCommon.scala:52) sbt.internal.inc.IncrementalCommon.cycle(IncrementalCommon.scala:265) sbt.internal.inc.Incremental$.$anonfun$incrementalCompile$8(Incremental.scala:409) sbt.internal.inc.Incremental$.withClassfileManager(Incremental.scala:496) sbt.internal.inc.Incremental$.incrementalCompile(Incremental.scala:396) sbt.internal.inc.Incremental$.apply(Incremental.scala:204) sbt.internal.inc.IncrementalCompilerImpl.compileInternal(IncrementalCompilerImpl.scala:542) sbt.internal.inc.IncrementalCompilerImpl.$anonfun$compileIncrementally$1(IncrementalCompilerImpl.scala:496) sbt.internal.inc.IncrementalCompilerImpl.handleCompilationError(IncrementalCompilerImpl.scala:332) sbt.internal.inc.IncrementalCompilerImpl.compileIncrementally(IncrementalCompilerImpl.scala:433) sbt.internal.inc.IncrementalCompilerImpl.compile(IncrementalCompilerImpl.scala:137) org.jetbrains.jps.incremental.scala.local.SbtCompiler.$anonfun$doCompile$3(SbtCompiler.scala:87) scala.util.Try$.apply(Try.scala:217) org.jetbrains.jps.incremental.scala.local.SbtCompiler.doCompile(SbtCompiler.scala:85) org.jetbrains.jps.incremental.scala.local.SbtCompiler.compile(SbtCompiler.scala:17) org.jetbrains.jps.incremental.scala.local.LocalServer.doCompile(LocalServer.scala:51) org.jetbrains.jps.incremental.scala.local.LocalServer.compile(LocalServer.scala:29) org.jetbrains.jps.incremental.scala.remote.Main$.compileLogic(Main.scala:210) org.jetbrains.jps.incremental.scala.remote.Main$.$anonfun$handleCommand$1(Main.scala:191) org.jetbrains.jps.incremental.scala.remote.Main$.decorated$1(Main.scala:178) org.jetbrains.jps.incremental.scala.remote.Main$.handleCommand(Main.scala:188) org.jetbrains.jps.incremental.scala.remote.Main$.serverLogic(Main.scala:161) org.jetbrains.jps.incremental.scala.remote.Main$.nailMain(Main.scala:101) org.jetbrains.jps.incremental.scala.remote.Main.nailMain(Main.scala) sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(Method.java:498) com.facebook.nailgun.NGSession.runImpl(NGSession.java:312) com.facebook.nailgun.NGSession.run(NGSession.java:198)
最新发布
11-18
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值