scala基础--面向对象(二)
Scala中的抽象类和特质是面向对象编程的重要概念。抽象类使用abstract关键字定义,可以包含抽象成员和具体成员,但不能直接实例化,必须通过子类继承实现。特质(trait)类似接口,支持多重继承,可以包含抽象和具体成员。两者主要区别在于:特质支持多重继承,而抽象类不支持;抽象类可以有构造参数,特质则没有。此外,Scala还支持匿名子类和伴生对象,匿名子类用于快速创建一次性使用的子类实例,伴生对
目录
抽象类
在scala中,抽象类是用abstract关键字修饰的类,他的核心特点是:
1.可以包含未实现的抽象成员(抽象方法,抽象字段),也可以包含已经实现的具体成员
2.不能直接实例化(无法new创建对象),必须通过子类继承并实现所有抽象成员后才能实例化
简单类比:抽象类就像一份"半成品设计图",规定了子类必须具备的功能(抽象成员),同时也提供了子类可以直接使用的通用功能(具体成员)
抽象属性/方法
基本语法:
1.定义抽象类:abstract class Person{} 通过abstract关键字标记抽象类
2.定义抽象属性: val|var name:String 一个属性没有初始化,就是抽象属性
3.定义抽象方法:def hello():String 只是声明而没有实现的方法,就是抽象方法
abstract class Person{
val name:String // 抽象属性
def hello():Unit // 抽象方法
}
// 抽象类不可以直接调用,必须由子类来继承使用
class Teacher extends Person {
val name:String = "teacher"
def hello():Unit = {
println("hello teacher")
}
}
抽象类的继承和重写
1.如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需声明
为抽象类2.重写非抽象方法需要用 override 修饰,重写抽象方法则可以不加 override 。3.子类中调用父类的方法使用 super 关键字4.子类对抽象属性进行实现,父类抽象属性可以用 var 修饰;子类对非抽象属性重写,父类非抽象属性只支持 val 类型,而不支持 var 。因为 var 修饰的为可变变量,子类继承之后就可以直接使用,没有必要重写
def main(args:Array[String]):Unit = {
val student = new Student
student.eat()
student.sleep()
}
// 定义一个抽象类
abstract class Person{
//非抽象属性
val name:String = "person"
// 抽象属性
var age:Int
// 非抽象方法
def eat():Unit = {
println("person eat")
}
// 抽象方法
def sleep():Unit
}
// 定义具体实现子类
class Student extents Person{
// 重写抽象属性和抽象方法
var age:Int = 18
def sleep():Unit = {
println("student sleep")
}
// 重写非抽象属性和方法,必须加上override
override val name:String = "student"
override def eat():Unit = {
super.eat()
println("student eat")
}
}
匿名子类
在 Scala 中,匿名子类 是指:不单独定义一个具名的子类(比如
class Cat extends Animal),而是在创建对象时,直接通过new 父类/特质 { ... }的方式,一次性 实现父类(通常是抽象类或特质)的抽象成员,并直接生成该子类的实例。简单类比:匿名子类就像 “临时定制” 的子类 —— 你不需要给它起名字,只用这一次,用完就丢,适合快速创建一个仅需单次使用的子类实例。
def main(args:Array[String]):Unit = {
val person = new Person{
override var name:String = "alice"
override def eat():Unit = {
println("person eat")
}
}
println(person.name)
person.eat()
}
abstract class Person {
var name:String
def eat():Unit
}
单例对象(伴生对象)
在 Scala 中,伴生对象 是指:
- 与一个类(称为 “伴生类”)同名的
object(单例对象);- 两者必须定义在同一个源文件中;
- 伴生对象和伴生类可以互相访问对方的私有成员(私有字段、私有方法),这是它最核心的特性;
- 伴生对象属于 “静态上下文”(类似 Java 的静态方法 / 字段),而伴生类是实例上下文。
单例对象语法
基本语法:
object Person{
val country:String = "china"
}
单例对象采用 object 关键字声明单例对象对应的类称之为 伴生类 ,伴生对象的名称应该和伴生类名一致。单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问
// 半生对象
object Person{
val school:String = "hbcsjs"
}
// 定义类
class Person(val name:String,val age:Int){
def printInfo(){
println(s"person:name = ${name},age = ${age},school=${Person.school}")
}
}
def main(args:Array[String]):Unit = {
val person = new Person("alice" , 18)
person.printInfo()
}
特质
特质和抽象类的区别
1. 优先使用特质。一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。2. 如果你需要构造函数参数,使用抽象类。因为抽象类可以定义 带参数 的构造函数,而特质不行(有无参构造)。
特质声明
Scala 语言中,采用特质 trait (特征)来代替接口的概念 ,也就是说,多个类具有相同的特质(特征)时,就可以将这个特质(特征)独立出来,采用关键字 trait 声明。Scala 中的 trait 中即 可以有抽象属性和方法,也可以有具体的属性和方法 , 一个类可以混入( mixin )多个特质 。这种感觉 类似于 Java 中的抽象类。Scala 引入 trait 特征,第一可以替代 Java 的接口,第二个也是对单继承机制的一种
特质基础语法
定义特质:
trait 特质名 {
trait主体
}
基本语法:
没有父类 : class 类名 extends 特质 1 with 特质 2 with 特质 3 …有父类 : class 类名 extends 父类 with 特质 1 with 特质 2 with 特质 3…说明:类和特质的关系:使用继承的关系。当一个类去继承特质时,第一个连接词是 extends ,后面是 with 。如果一个类在同时继承特质和父类时,应当把父类写在 extends 后。
案例演示:
def main(args:Array[String]):Unit = {
var student = new Students
student.sayHello()
student.study()
student.dating()
student.play()
}
// 定义一个父类
class Person1{
val name:String = "person"
var age:Int = 18
def sayHello():Unit = {
println("hello from" + name)
}
}
// 定义一个特质
trait Young{
// 声明抽象和非抽象属性
var age:Int
val name:String = "young"
// 抽象和非抽象方法
def play():Unit = {
println("young people is playing")
}
def dating():Unit
}
class Students extends Person1 with Young{
// 重写冲突属性
override val name:String = "student"
// 实现(重写)抽象方法
def dating():Unit = {
println(s"student ${name} is dating")
}
// 创建方法
def study():Unit = {
println(s"student ${name} is studying")
}
// 重写父类方法
override def sayHello():Unit = {
// 先调用父类方法
super.sayHello()
println(s"hello from:student ${name}")
}
}
更多推荐


所有评论(0)