Scala对象

目录

类的定义和使用

主构造器 and 附属构造器

继承

抽象类

伴生类和伴生对象 & apply

case class

trait

类别名


 

类的定义和使用

  • 关于占位符
    • 使用_的地方
      • 作为局部变量,需要重新赋值,才能再使用,例如打印等
      • 作为成员变量,其实就是该类型的默认值,可以直接使用,例如打印
        • 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生态圈,收获高薪未来

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值