Scala的面向对象思想和Java的面向对象思想和概念是一致的。 但Scala中又补充了更多的功能。
在Scala中可以为每个包定义一个同名的包对象,定义在包对象中的成员,作为其对应包下所有class和object的共享变量,可以被直接访问。
定义示例:
package object com { val shareValue = "Share" def shareMethod() = {} }
例如:
//引入com.atguigu包下的所有成员,并将Fruit更名为Shuiguo import com.atguigu.{Fruit=>Shuiguo,_} //引入com.atguigu包下屏蔽Fruit类 import com.atguigu.{Fruit=>_,_} //引入的Java的绝对路径 new _root_.java.util.HashMap
注意:Scala中有三个默认导入的包
import java.lang._ import scala._ import scala.Predef._
Java:
如果类是public的,则必须和文件名一致。一般,一个.java有一个public类 。
Scala:
Scala中没有public,一个.scala中可以写多个类。 (默认类就是公共的)
Scala中Bean属性(@BeanPropetry),可以自动生成规范的setXxx/getXxx方法,例如:
class Person{ //给属性赋默认值 var name: String = _ //注意:val不能赋默认值 val age: Int = 18 @BeanProperty var sex: String = "男" } object Person { def main(args: Array[String]): Unit = { val person = new Person() println(person.name) person.setSex("女") println(person.getSex) } }
注意:Scala中的public属性,底层实际为private,并通过get方法(obj.field())和set方法(obj.field_=(value))对其进行操作。所以Scala并不推荐将属性设为private,再为其设置public的get和set方法的做法。但由于很多Java框架都利用反射调用getXXX和setXXX方法,有时候为了和这些框架兼容,也会为Scala的属性设置getXXX和setXXX方法(通过@BeanProperty注解实现)。
在Java中,访问权限分为:public,private,protected和默认。在Scala中,你可以通过类似的修饰符达到同样的效果。但是使用上有区别。
基本格式:
val | var 对象名 [:类型] = new 类型()
注意:
和Java一样,Scala构造对象也需要调用构造方法,并且可以有任意多个构造方法。
Scala类的构造器包括:主构造器和辅助构造器 。
//这就是主构造器 class Dog(){ var sex: Int = _ var name: String = _ //辅助构造器,可以有多个 //注意:每个辅助构造器都必须以一个对先欠已经定义的其他构造器调用先开始 def this(name: String){ //直接调用主构造器方法 this() println("第一个辅助构造器被调用了") this.name = name } def this(sex: Int,name: String){ //调用第一个辅助构造器 this(name) println("第二个辅助构造器被调用了") this.sex = sex } } object Dog { def main(args: Array[String]): Unit = { var d1 = new Dog("可乐")//这是第一个辅助构造器 var d2 = new Dog(2,"妞妞") //这是第二个辅助构造器 } } 输出: 第一个辅助构造器被调用了 第一个辅助构造器被调用了 第二个辅助构造器被调用了
Scala继承一个基类跟Java很相似, 但我们需要注意以下几点:
class Person{ //给属性赋默认值 val name: String = "zhangsan" //注意:val不能赋默认值 val age: Int = 18 @BeanProperty var sex: String = "男" def hello() = { println("这是Person类") } } class Emp extends Person { //重写父类属性 //注意:只能重写 val 属性 override val name: String = "小明" //重写父类方法 override def hello(): Unit = { super.hello() println("这里是子类") } } object Person { def main(args: Array[String]): Unit = { val person = new Person() person.hello() val emp = new Emp() emp.hello() //Scala中的多态 val emp2: Person = new Emp() println(emp2.name) } }
基本语法:
注意事项:
和Java一样,可以通过包含带有定义或重写的代码块的方式创建一个匿名的子类。
abstract class Person{ //抽象属性 val name: String //抽象方法 def hello():Unit } object ObjectTest { def main(args: Array[String]): Unit = { val person = new Person { //定义匿名类 override val name: String = "zhangsan" override def hello(): Unit = println("我是匿名类") } } }
Scala语言是完全面向对象的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,该对象为单例对象。若单例对象名与类名一致,则称该单例对象这个类的伴生对象,这个类的所有“静态”内容都可以放置在它的伴生对象中声明。
说明:
//单例类,即半生对象,不可以又参数 object Person{ } //与半生对象同名相对应的半生类 //可以有参数 class Person(){}
说明;
//注意:传入的参数名不要和属性名相同,否则程序错误 //如果想让主构造器变成私有的,可以在()之前加上private class Cat private(sName: String){ var name: String = sName } //单例类,即半生对象,不可以又参数 object Cat{ def apply(): Cat = { println("apply 空参被调用") new Cat("xx") } def apply(name: String): Cat = { println("有参 apply被调用") new Cat(name) } } object ObjectTest02 { def main(args: Array[String]): Unit = { //不使用new 创建对象 //使用伴生对象apply方法创建对象,调用无参apply方法 val cat1= Cat() //调用有参apply方法 val cat2 = Cat("xiaomiao") } }
Scala语言中,采用trait(特征)来代替接口的概念,也就是说,多个类具有相同的特质(特征)时,就可以将这个特质(特征)独立出来,采用关键字trait声明。
Scala中的trait中即可以有抽象属性和方法,也可以有具体的属性和方法,一个类可以混入(mixin)多个特质。这种感觉类似于Java中的抽象类。
Scala引入trait特征,第一可以替代Java的接口,第二个也是对单继承机制的一种补充。
基本语法:
trait 特质名 { trait主体 }
一 个类具有某种特质(特征),就意味着这个类满足了这个特质(特征)的所有要素,所以在使用时,也采用了extends关键字,如果有多个特质或存在父类,那么需要采用with关键字连接。
基本语法:
没有父类:class 类名 extends 特质1 with 特质2 with 特质3 …
有父类:class 类名 extends 父类 with 特质1 with 特质2 with 特质3…
说明:
代码示例:
trait PersonTrait{ //创建具体的属性和方法 var name: String = "" def eat() = { println("eat") } //创建抽象的属性和方法 var age: Int def say(): Unit } trait SexTrait{ var sex: String } //一个类可以实现/继承多个特质 //所有的Java接口都可以当做Scala特质使用 class Student extends PersonTrait with java.io.Serializable{ override var age: Int = 16 override def say(): Unit = println("我是一名学生") } object PersonTrait { def main(args: Array[String]): Unit = { val student = new Student() student.say() student.eat() //动态混入trait //只混入该对象,而不会混入该类 val student1 = new Student() with SexTrait{ override var sex: String = "男" } //调用混入的属性 println(student1.sex) } }