1. 类和属性

1.1 如何控制构造函数字段的可见性

在Scala中:

  1. 如果一个字段被声明为var, Scala会为该字段生成getter和setter方法。
  2. 如果字段是val, Scala只生成getter方法。
  3. 如果一个字段没有var或者val的修饰符, Scala比较保守,不会生成getter和setter方法。
  4. 另外,var和val字段可以被private关键字修饰,这样可以防止生成getter和setter方法。

我们看一下测试代码:

object Demo{
def main(args: Array[String]): Unit = {
val p = new Person("haah")
println(p.name)
} class Person(var name:String){ }
}
结果:
haah

我们再把name设置为val:

还没有到运行阶段,编译器自动捕获了异常。改为var就可以了。

如果设置为非val和非var的字段:

直接找不到name这个对象,当构造函数参数既没有声明为val或var时,字段的可见性很受限制,井且Scala不会为此生成访问修改方法。

给val或者var加上private,这个关键字会阻止getter和setter方法的生成,所以这种宇段只能被类的成员变量使用。

2. 构造函数

如同在java中可以定义多个构造函数,Scala中也可以,不同的是除了主构造函数以外其余的构造函数都被称为辅助构造函数。所有的辅助构造函数必须以this为名,另外每个构造函数必须调用之前已经定义好了的构造函数:

//主构造函数
class MakePizza(var size:Int,var pizzaType:String){
//辅构造函数
def this(pizzaAuthor:String){
this(size,"3")
}
//辅构造函数
def this(){
this("libai")
} }

定义私有主构造函数:

class Order private{

}

私有构造函数是无法实例化的。我们知道在java中实现单例模式就是把构造函数私有化。提供一个getInstance方法来初始化类。

class MakePizza private (var size:Int,var pizzaType:String){

  object getInstance extends MakePizza(size,pizzaType){
val makePizza = new MakePizza(size,pizzaType)
} }

设置构造函数参数默认值

class Socket(var timeout:Int = 10000)

那么在调用构造函数的时候就可以不指定默认值:

val s = new Socket

用case类生成模板代码:

定义case类可以生成模板类,包括如下方法:apply,unapply,toString,equals,hashCode。

case class  Person(name:String,relation:String)

将类定义为case类会生成许多模板代码,好处在于:

  1. 会生成一个apply方怯,这样就可以不用new关键字创建新的实例。
  2. 由于case类的构造函数参数默认是val ,那么构造函数参数会自动生成访问方站。如果是var也会有修改方怯。
  3. 会生成一个默认的toString方怯。
  4. 会生成一个unapply方法,在模式匹配时很好用。
  5. 会生成equals和hashCode方法。
  6. 还有一个copy方站。

定义case类,就不用再new来创建一个实例:

val wmily = Person("xiaoming","niece")

case类的构造参数默认是val,所以会自动生成get方法,不会生成set。当把case类的构造方法参数设置为var的时候就会有get和set。

case类主要是为了创建“不可变的记录”,这样容易在模式匹配中使用。正因为如此,casel的构造函数参数默认值是val,如果你改为var那就违背了case的本意。

3. 方法

在java中声明一个方法如下:

public String doSomething(int x){

}

在scala中则是这样:

sef doSomeThing(x:Int):String = {

}

控制方法的作用域:

Scala中的方法缺省是public。

在java中protected修饰的方法对同一包中的类都可见。但是在Scala中仅对该类的子类可见。

下表中给出了Scala中各种级别的访问控制:

修饰符 描述
private[this] 对当前实例可见
private 对当前类的所有实例可见
protected 对当前类以及其子类的实例可见
private[model] 对model包下的所有类可见
private[coolapp] 对cooapp包下的所有类可见
private[acme] 对acme包下的所有类可见
无修饰符 公开方法

调用父类中的方法:

Scala中调用父类,用super代表父类,然后是方法名:

class App extends Fruit{
override def onCreate(color:String){
super.onCreate(color)
}
}

可以继承多个类:

与java中不同的是Scala的类对象可以同时继承多个类。如果继承的多个类中有相同的方法可以用如下方式选择要使用哪个类中的方法:

super[类名].方法名

举个例子:

object Demo{
def main(args: Array[String]): Unit = {
var a = new ShowColor
a.printApple("red")
a.printBanana("yellow") }
} trait Fruit{
def getColor(color: String): Unit ={
printf("the color is %s \n",color)
}
} trait Apple extends Fruit{
override def getColor(color: String): Unit = super.getColor(color)
} trait Banana extends Fruit{
override def getColor(color: String): Unit = super.getColor(color)
} class ShowColor extends Fruit with Apple with Banana{
def printSuper(color: String) = super.getColor(color: String)
def printApple(color: String) = super[Apple].getColor(color: String)
def printBanana(color: String) = super[Banana].getColor(color: String)
} 结果:
the color is red
the color is yellow Process finished with exit code 0

方法参数默认值:

如同python一样,Scala可以给方法的参数一个默认值:

def makeCnnection(timeout:Int = 3000,[protocol:String="http"){
println("timeout = %d,protocol=%s".format(timeout,protocol))
}

定义一个返回多个值(tuples)的方法

如果我们希望一个方法能够返回多个值,又不想把这些值字段用一个对象包装,那么可以使用tuples从方法中返回多个值。

tuples是Scala中的数据类型,表示元组的意思。元组是使用()表示的数据结构。后面我们介绍集合列表的时候会详细说。

加入有如下方法返回了包含3个字段的元组:

def getStackInfo = {
return ("RPC","sufface",34)
}

可以使用一个元组来接收:

val result = getsStackInfo
println(b._1,b._2,b._3)

tuple中的值可以通过其位置来访问。

可变参数的方法

在java中可以传入String 类型的可变参数:String … str,在Scala中也提供可变参数的方法:在参数类型后面加一个 “*”,这个参数就变成了可变参数。

def printAll(str:String*){

}

注意:同java一样,当一个方法包含可变参数的时候,那么这个可变参数必须是在所有参数中最后一个位置,否则会报错。

使用_*来匹配一个序列

对于一个序列:Array,List,Seq,Vector,都可以使用_*来匹配里面的每一个对象,从而可以使他可以当做变参传递给一个方法:

def main(args: Array[String]): Unit = {
val fruit = List("apple","banana","pair")
printAll(fruit: _*)
} def printAll(str:String*): Unit ={
str.foreach(println)
}

解析fruit的每一个对象然后作为参数传递给printAll()方法。

方法的异常声明

使用@throws注解声明可能抛出的异常。这个和java中的使用方式有区别。

@throws(classOf[Exception])
def paly: Unit ={
//code....
}

4. 对象

对象的强制转换:

使用asInstanceOf将一个实例转换为期望的类型。

val recongnizer = cm.lookup("recongnizer").asInstanceOf[Recognizer]

上面的Scala代码等于下面的java代码:

Recognizer recognizer = (Recognizer)cm.lookup("Recognizer");

java中的对象.class的Scala等价类

在java中当你有一个方法里面要求将不同的对象作为参数传进来然后使用不同对象的不同方法,这个时候你可以传入一个参数:class clz。然后利用反射获取不同对象的方法。

在Scala中使用classOf方法来代替java中的.class。

val info = new DataLine.Info(classOf[TargetDataLine],null)

等价于java中的:

info = new DataLine.info(TargetDataLine.class,null)

用object 启动一个应用:

在Scala中启动一个应用有两种方法:

  1. 定义继承App特质的object;
  2. 定义一个object,并实现main方法

    object Demo{

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

    println(“hello”)

    }

    def printAll(str:String*): Unit ={

    str.foreach(println)

    }

    }

或者:

object Hello extends App{
println("hello")
}

不用new关键字创建对象实例:

有两种办法:

  1. 为类对象创建伴生类,并在伴生类内定义一个apply方法;
  2. 将类定义为case类。

用apply方法创建一个伴生类:

class Person{
var name:String = ""
} object Person{
def apply(name:String): Person = {
var p = new Person
p.name = name
p
}
}

调用方式:

val carry = Person("carry")

在同一个文件中定义Person类和Person对象,在对象中定义apply方法接受期望的参数,这个方法本质上是类的构造函数。

将类声明为case类:

case class Person(var name:String)
val p = Person("carry")

case类起的作用在于他在伴生类中生成了一个apply方法,上文我们已经说过将一个类定义为case类会自动生成很多方法。

5.包管理

Scala的包管理跟Java类似,但更灵活。除了在类文件的开头用package语句外,还可以用花括号,与C++和C#的命名空间很像。

Scala会隐式的导入两个包:

java.lang._
scala._

Scala里的”_”字符类似于java里的”*”。

5.1 花括号风格的包记号法:
package com.rickiyang.zoo{
class Foo{
//todo
} class food{
//todo
}
}

这种方式允许在一个文件中放多个包。也可以用“花括号”方式定义嵌套的包。

5.2 在导入时重命名类名:
import java.util.{ArrayList => JavaList}

然后再代码中就可以使用别名了。

当你为你的类取了别名后那么原来的名字就不可以使用了。否则会出错。

6. 特质—>java中的接口

上文中我们使用过trait修饰类,trait就是Scala中的特质,相当于java中的接口。正如Java类能够实现多个接口一样, Scala类可以继承多个特质。所以trait的功能要比java接口的功能要强大的多。

做为普通的接口来使用:

方法如果不需要任何参数,在def后面指定方法名即可:

trait BasePlay{
def playBasketBall
def playFootBall
}

需要参数只需要将其罗列出来:

trait BasePlay{
def playBasketBall(count:Int)
def playFootBall(count:Int)
}

当一个类需要继承特质时,要使用extends和with关键字。只继承一个特质时,使用extends:

class BasketBall extends BasketBall{
//todo
}
  • 继承一个类和一个或多个特质时,对类使用extends ,对特质使用with。
  • 当一个类继承多个特质时,使用extends继承第一个特质,其余的使用with 。
  • 除非实现特质的类是一个抽象类,否则它必须实现特质所有的抽象方怯。
  • 如果一个类继承了一个特质但是没有实现它的抽象方法,这个类必须被声明为抽象类。
  • 特质也可以继承另一个特质。

像抽象类一样使用特质:

定义为trait的类中既可以有抽象方法也可以有已经实现了的方法。

trait BasePlay{
def playBasketBall {println("haha")}
def playFootBall
} class Football extends BasePlay {
override def playFootBall: Unit = {
println("hahahh football")
}
}

对于trait中已经实现了的方法,他的继承类可以重写也可以不重写。但是抽象方法一定要重写,否则继承类必须定义为抽象类(abstract)。

Scala类和对象(二)的更多相关文章

  1. Scala实战高手****第9课:Scala类和对象彻底实战和Spark源码鉴赏

    scala类和对象 RDD中创建_sc和deps相比java更加的简洁. 在Spark的例如SparkContext.sqlSpark等全局成员在完成实例化. 在唯一实例的时候一般不会去使用伴生对象a ...

  2. Spark记录-Scala类和对象

    本章将介绍如何在Scala编程中使用类和对象.类是对象的蓝图(或叫模板).定义一个类后,可以使用关键字new来创建一个类的对象. 通过对象可以使用定义的类的所有功能. 下面的图通过一个包含成员变量(n ...

  3. C++中的类和对象(二)

    一,对象的动态建立和释放 1.什么是对象的动态建立和释放 通常我们创建的对象都是由C++编译器为我们在栈内存中创建的,我们无法对其进行生命周期的管理.所以我们需要动态的去建立该对象,因此我们需要在堆内 ...

  4. Scala 类和对象

    Scala class: Scala 源文件中可以有很多类(class),这些类默认都是Public的,public是Scala的默认访问级别.在Scala中,声明一个未用priavate修饰的字段 ...

  5. Scala类与对象

    类简介 简介 类是对象的蓝图.一旦你定义了类,就可以用关键字new根据类的蓝图创建对象.在类的定义里,可以放置字段和方法,这些被笼统地称为成员.对于字段,不管是val还是var定义的,都是指向对象的变 ...

  6. Scala类和对象

    1.面向对象 Scala的类与java.C++的一些比起来更简洁,速度更快 对象:使用object关键字修饰的 类:使用class关键字修饰的new Person()实例对象 new类:类的实例(对象 ...

  7. scala 类,伴生对象

    1.属性的定义 编写一个PersonS类,并在其中定义一些属性,通过PersonS.scala 编译后的情况查看,可以知道不同修饰符修饰的属性分别会生成什么方法(set,get) package co ...

  8. Spark记录-Scala类与对象小例子

    //基类-Person class Person(val na: String, val ag: Int) { //属性 var name: String = na var age: Int = ag ...

  9. php类和对象(二)

    面向对象第三大特性:多态 概念: 当父类引用指向子类实例的时候,由于子类对父类函数进行了重写,导致我们在使用该引用取调用相应方法时表现出的不同 条件: 1.必须有继承 2.子类必须对父类的方法进行重写 ...

随机推荐

  1. Codeforces 782B:The Meeting Place Cannot Be Changed(三分搜索)

    http://codeforces.com/contest/782/problem/B 题意:有n个人,每个人有一个位置和速度,现在要让这n个人都走到同一个位置,问最少需要的时间是多少. 思路:看上去 ...

  2. java获取config下文件

    private static final String keystore="keystore.jks"; InputStream is=Thread.currentThread() ...

  3. centos7安装hadoop完全分布式集群

    groupadd test             //新建test工作组 useradd -g test phpq        //新建phpq用户并增加到test工作组 userdel 选项 用 ...

  4. HashMap源码分析(一):JDK源码分析系列

    正文开始 注:JDK版本为1.8 HashMap1.8和1.8之前的源码差别很大 目录 简介 数据结构 类结构 属性 构造方法 增加 删除 修改 总结 1.HashMap简介 HashMap基于哈希表 ...

  5. easyui datagrid 单元格 编辑时 事件 修改另一单元格

    //datagrid 列数据 $('#acc').datagrid({ columns : [ [ { field : 'fee_lend', title : '收费A', width : 100, ...

  6. Java编程思想:File类其他方法

    import java.io.File; public class Test { public static void main(String[] args) { MakeDirectories.te ...

  7. 使用R语言预测产品销量

    使用R语言预测产品销量 通过不同的广告投入,预测产品的销量.因为响应变量销量是一个连续的值,所以这个问题是一个回归问题.数据集共有200个观测值,每一组观测值对应一种市场情况. 数据特征 TV:对于一 ...

  8. something good

    CF292A CF304B CF383A CF409D CF409F CF632A CF652B CF656A CF656B CF656D CF659A CF678A CF697A CF735D CF ...

  9. app同包同签名不能安装问题

    今天博主与团队之间出现一个很郁闷的问题: 那就是我们开发的一个app,在升级推送版本的时候突然出现,相同的包名.相同的签名.在安装的时候出现,安装签名不一致(安装失败)的提示. 让我们很是困扰.后来发 ...

  10. CSS(下)

    1.CSS边框 边框属性: 1.border-width 宽度 2.border-style 样式 none 无边框 dotted 点状虚线边框 dashed 矩形虚线边框 solid 实线边框 3. ...