目录
类的定义和使用
- 关于占位符
- 使用_的地方
- 作为局部变量,需要重新赋值,才能再使用,例如打印等
- 作为成员变量,其实就是该类型的默认值,可以直接使用,例如打印
- Char -> ?, String -> null, Int -> 0
- val修饰的变量不能使用_
- 使用占位符,必须明确写出类型
- 例如:var b: Boolean = _
- 不能写成:var b = _,会报错:error: unbound placeholder parameter *,因为不明确写出类型,scala会依据右侧所赋值的类型进行类型推断,占位符没有类型,无法
- 使用_的地方
成员变量必须赋值,或用占位符占住(看成默认值)
关于访问范围,通过private []来约束,其中[]中表示范围,例如[this]本类可见,[包名]某包下可见
object SimpleObjectApp {
def main(args: Array[String]): Unit ={
val person = new People()
person.name = "Messi"
println(person.name + ".." + person.age)
println("invoke eat method: " + person.eat)
person.watchFootball("Barcelona")
person.printGender()
// println(person.gender) // private [this]修饰的变量只能在其定义的类内部访问
println(person.visit)
}
}
class People{
// Scala中变量会自动生成get/set,其中_是占位符
var name: String = _
// Scala中常量会自动生成get
val age = 10
private [this] val gender = "male" // private [this]修饰的变量只能在其定义的类内部访问
private [course04] val visit = "visited" // private [course04]修饰的变量只能在course04包下访问
def printVisit(): Unit = println("visit: " + visit)
def printGender()= println("gender: " + gender)
def eat()= name + " eat..."
def watchFootball(teamName: String): Unit = {
println(name + " is watching match of " + teamName)
}
}
主构造器 and 附属构造器
- 跟在类名后的是主构造器
- 附属构造器,def this(参数列表){},这边不需要在:返回值类型=
- 附属构造器的第一行代码必须调用主构造器或者其他附属构造器
- 构造器中最后一个表达式的值不会被返回,而是被忽略,构造器本来就是为了实例化对象的,故此处不会有返回值啥事
class Drink(val name: String = ""){
//class Drink needs to be abstract, since variable price is not defined
//(Note that variables need to be initialized to be defined)
//class Drink(val name: String = ""){
// var price: Double //报错
var price: Double = _ // 若后续没有赋值,则是默认值0.0
def this(name: String, price: Double){
this(name)
this.price = price
println(name + "的价格是" + price)
34 // 构造器中最后一个表达式的值不会被返回,而是被忽略
}
def info(){println("info: " + name + "的价格是" + price)}
}
继承
- 若是继承自父类的,则不能写var或val,否则需要加重写字样
- 若是子类特有的则必须写val或var,否则外部不能访问
- 父类中的常量
- 例如name: String,若写成val name: String,则会报错,Parameter 'name' needs override modifier
- 而且只能是override val name: String, 若是override var name: String,会报错,variable name cannot override immutable value
- 父类中的变量:例如age: Int, 却是可以写成override val age: Int的
- 重写父类的方法和属性需要在前面添加override关键字
object ConstructorApp {
def main(args: Array[String]): Unit ={
val person = new Person("Amy", 20)
println(person.name + " : " + person.age + " : "
+ person.school + " : " + person.gender + "\n")
val person2 = new Person("Pk", 18, "M")
println(person2.name + " : " + person2.age
+ " : " + person2.school + " : " + person2.gender + "\n")
val student = new Student("PK", 18, "Math")
println(student.name + " : " + student.major + "\n")
println(student.toString)
}
}
// 跟在类名后的是主构造器
class Person(val name: String, var age: Int){ // 此处如果不写val则外部不能访问到name
println("Person Constructor enter...")
val school = "ustc"
var gender: String = _
println("Person Constructor leave...")
// 附属构造器
def this(name: String, age: Int, gender: String){
this(name, age) // 附属构造器的第一行代码必须调用主构造器或者其他附属构造器
this.gender = gender
println("Person 附属构造器 leave...")
}
override def toString: String = "Person override def toString"
}
// 若是子类特有的则必须写val或var,否则外部不能访问
// 若是继承自父类的,则不能写var或val
// 例如name: String,若写成val name: String,则会报错,Parameter 'name' needs override modifier
// 而且只能是override val name: String, 若是override var name: String,会报错,variable name cannot override immutable value
// 但是age: Int, 却是可以写成override val age: Int的
class Student(name: String, age: Int, val major: String) extends Person(name, age){
println("Person Student enter...")
// 重写父类的方法和属性需要在前面添加override关键字
override val school = "peking"
override def toString: String = "Student override def toString " + school
println("Person Student leave...")
}
输出:
Person Constructor enter...
Person Constructor leave...
Amy : 20 : ustc : null
Person Constructor enter...
Person Constructor leave...
Person 附属构造器 leave...
Pk : 18 : ustc : M
Person Constructor enter...
Person Constructor leave...
Person Student enter...
Person Student leave...
PK : Math
Student override def toString peking
抽象类
- 若抽象类中有未实现的函数或者属性,则其子类要么继续做抽象类,要么将这些全部重写
- 不能实例化抽象类的对象
object AbstractApp {
def main(args: Array[String]): Unit = {
val student = new Student2()
student.speak
}
}
/**
* 类的一个或者多个方法没有完整实现(只有定义,没有实现)
*
*/
abstract class Person2{
// 方法和属性都可以是没有实现的
def speak
val name:String
val age:Int
}
class Student2 extends Person2{
override def speak = println("speak ")
override val name: String = "PK"
override val age: Int = 18
}
输出
speak
伴生类和伴生对象 & apply
伴生类和伴生对象
- 若有一个class,还有一个同名的object
- 则称这个object是class的伴生对象(但是有一点比较奇怪的是,这个伴生对象貌似没有走伴生类的构造),class是object的伴生类
apply
- 类名() == >object.apply
- 对象() == > class.apply
object ApplyApp {
def main(args: Array[String]): Unit = {
println("\n" + "===========伴生对象感觉有一点点像单例模式==========")
for(i <- 1.to(10)){
ApplyTest.incr
}
println(ApplyTest.count)
/**
* 类名() ==> object.apply
* 对象() ==> Class.apply
*/
println("\n" + "==========类名() == >object.apply===========")
val b = ApplyTest() // ==> 调用了object里面的apply方法
println("\n" + "===========对象() == > class.apply==========")
val c = new ApplyTest()
println(c)
c() // ==> 调用了class里面的apply方法
println("\n" + "===========伴生对象感觉有一点点像单例模式==========")
for(i <- 1.to(10)){
ApplyTest.incr
}
println(ApplyTest.count)
}
}
/**
* 伴生类和伴生对象
* 若有一个class,还有一个同名的object
* 则称这个object是class的伴生对象,class是object的伴生类
*/
class ApplyTest{
println("class ApplyTest enter....")
def apply()={ // 一定叫apply,名字别错哈
println("class ApplyTest apply....")
new ApplyTest
}
}
object ApplyTest{
println("object ApplyTest enter....")
var count = 0
def incr={
count = count + 1
}
// 最佳实践: 在object中的apply方法中去new class
def apply()={ // 一定叫apply,名字别错哈
println("object ApplyTest apply....")
// 在object中的apply中new class
new ApplyTest // 最后一行是返回值,可以认为返回了一个ApplyTest的对象
}
println("object ApplyTest leave....")
}
输出
===========伴生对象感觉有一点点像单例模式==========
object ApplyTest enter....
object ApplyTest leave....
10
==========类名() == >object.apply===========
object ApplyTest apply....
class ApplyTest enter....
===========对象() == > class.apply==========
class ApplyTest enter....
com.imooc.scala.course04.ApplyTest@c038203
class ApplyTest apply....
class ApplyTest enter....
===========伴生对象感觉有一点点像单例模式==========
20
case class
- case class 不用new
- 通常用在模式匹配里面
-
会自动将所有参数类型创建为val,若想要var则须明确指定,且我们能看到尽管构造器中没有写val或var,但是在类的外部我们依旧可以访问name
- print信息的时候,和普通类也有区别,普通类显示类似org.example.ch3.Cat@6bdf28bb,case的显示类似Dog(waicai),可以看到对象的属性。
// 通常用在模式匹配里面
object CaseClassApp {
def main(args: Array[String]): Unit = {
val dog = Dog("waicai")
println(dog)
println(dog.name)
println(new Cat("mimi"))
}
}
// case class 不用new
case class Dog(name: String)
class Cat(name: String)
trait
class xxx extends ATrait with BTrait
多个Trait用with连接,例如
class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging with Serializable
类别名
type 别名 = 类名
case class HelloWorldClass(s: String)
//expected class or object definition
//type Hello = HelloWorldClass // 放在这报错
object Bravity {
def filterWithYeild(v: Vector[Int]): Vector[Int] =
for{n <- v; if n < 10; if n % 2 != 0}
yield n
def main(args: Array[String]): Unit ={
val v = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
println(filterWithYeild(v))
type Hello = HelloWorldClass
println(HelloWorldClass("long "))
//not found: value Hello
// println(Hello("short")) // 报错:
println(new Hello("short")) // 因为是别名,所以必须用new 关键字?
println(new HelloWorldClass("long new ")) // 用不用new关键字都可以
}
}
参考:慕课网-学习Scala进击大数据Spark生态圈,收获高薪未来