Scala之面向对象

Scala面向对象详解
这篇博客详细介绍了Scala的面向对象特性,包括类的定义、内部类、构造器、Object对象、apply方法、继承、特质以及包和包对象的使用。特别强调了Scala中对象的私有属性访问控制和apply方法在对象创建时的作用。

Scala的面向对象:类似Java

把数据属性及数据操作的方法放在一起,作为一个依存的整体,就是对象。

一、面向对象的基本概念

1、封装:类class
2、继承
3、多态

二、类的定义

关键字class。

2.1 简单类和无参数方法。

class Counter{
private var value=0;
def increment(){}
def current()=value;
}

2.2 创建类

//注意:class前面没有public修饰

  • 举例:创建一个学生类
//代表一个学生的信息
class Student1 {
  //定义学生的属性
  private var stuID:Int = 0
  private var stuName:String = "Tom"
  private var age:Int = 20
  
  //定义成员方法(函数):get 和set
  //定义名字和年龄的get和set  
  def getStuName():String = stuName
  def setStuName(newName:String) = this.stuName = newName
  
  def getStuAge():Int = age
  def setStuAge(newAge:Int) = this.age = newAge
}

//如果要开发main方法,需要在main方法中定义该类的伴生对象
//测试Student1类,创建main函数(写到Object中)
//注意:object和class的名字可以不一样,如果一样了,这个object就叫做该class的伴生对象
object Student1{
  def main(args: Array[String]): Unit = {
    //创建学生对象
    var s1 = new Student1
    
    //第一次访问属性并输出
    println(s1.getStuName()+"\t"+s1.getStuAge())
    
    //访问set方法
    s1.setStuName("Mary")
    s1.setStuAge(22)
    println(s1.getStuName()+"\t"+s1.getStuAge())
    
    //再输出一次:直接访问私有的属性
    println("*************直接访问私有的属性************")
    println(s1.stuID +"\t"+ s1.stuName+"\t"+s1.age)
    
    //注意:可以直接访问类的私有成员  为什么可以? ----> 属性的get和set方法
    
  }
}

2.3 getter和setter方法

当定义属性是private时候,scala会自动为其生成对应的get和set方法。

private var stuName:String = "Tom"
  • get方法: stuName ----> s2.stuName() 由于stuName是方法的名字,所以可以加上一个括号
  • set方法: stuName_= ----> stuName_= 是方法的名字

定义属性:private var money:Int = 1000 希望money只有get方法,没有set方法??
办法:将其定义为常量private val money:Int = 1000。

  • private[this]的用法:
    该属性只属于该对象私有,就不会生成对应的set和get方法。如果这样,就不能直接调用,例如:s1.stuName —> 错误。

在Scala中,方法也可以访问该类的所有对象的私有字段,成为类私有字段;
但在Scala中,允许定义更加严格的字段访问控制,通过private[this]来实现,称为对象私有字段,即只能在对象内部访问的字段,
private[this] val money:Int = 1000
def test(other:Person)=this.money.equal(other.money)
方法内不能访问其他对象的对象私有字段(salary)。

三、内部类

内部类(嵌套类):就是在一个类的内部,定义了另外一个类。

object Student2{
  def main(args: Array[String]): Unit = {
    var s2 = new Student2
    s2.addNewCource("chinese",1)
    s2.addNewCource("math",2)
    s2.addNewCource("english",3)

    //输出
    println(s2.stuName,s2.stuAge)

    //遍历选的课
    for (s <- s2.courseList) println(s.courseName+":"+s.creditId)
  }
}


class Student2 {
  //定义一个内部类,记录学生选课信息
  //这里定义了该类的主构造器
  class Course(val courseName:String,val creditId:Int){

  }
  private var stuName:String="Tom"
  //抽象属性可以不被初始化
  // var stuAge:Int =0
  private var stuAge:Int=18

  //定义一个ArrayBuffer记录学生选修的所以课程
  private var courseList = new ArrayBuffer[Course]()

  def addNewCource(cname:String,creditId:Int): Unit ={
    //创建新课程
    var c=new Course(cname,creditId)
    //将课程加入list
    courseList+=c

  }

四、类的构造器:两种

1、主构造器:和类的声明在一起,并且一个类只有一个主构造器。
2、辅助构造器:一个类可以有多个辅助构造器,通过关键字this。
       相当于java中构造器调用其它构造器。
object Student3 {
  def main(args: Array[String]): Unit = {
    val s3=new Student3("123")
    print(s3.stuName+":"+s3.stuAge)
  }

}

//主构造器和类的声明在一起
//只能有一个主构造器
class Student3(var stuName:String,var stuAge:Int) {
//两种写法
  def this(stuName: String) = this(stuName, 20)
  //辅助构造器
  def this(stuAge: Int) {
    //主构造器
    this("123", 20)
  }
}

类的构造器分为:主构造器、辅助构造器

五、Object对象:相当于Java中的static。

Scala没有静态的修饰符,但Object对象下的成员都是静态的 ,若有同名的class,将其作为它的伴生类。
在Object中一般可以为伴生类做一些初始化等操作。

1、Object中的内容都是静态的
2、Scala中,没有静态修饰符static
3、如果class的名字,跟object的名字一样,这时候就把这个object叫做类的伴生对象
4、举例
(1)使用object实现单例模式:一个类只有一个对象。
如果在Java中,构造器定义为private,提供getInstance方法
(2)使用App对象:应用程序对象。
好处:可以省略main方法

/**
  * scala中的object相当于静态代码块
  * 利用object对象实现单例
  */
object CreditCard {

  //变量保存信用卡号【this】,即该属性只属于该对象
  private[this] var creditCardNumber:Int=0

  //注意:当是基本数据类型的时候需要进行返回。是Unit的时候不需要返回。
  //这个方法由于定义在object中,所以是静态的
  def generateNewCCNumber():Long={
    creditCardNumber +=1
    creditCardNumber
  }

  def main(args: Array[String]): Unit = {
    println(generateNewCCNumber())
    println(generateNewCCNumber())
    println(generateNewCCNumber())
    print(creditCardNumber)
  }

六、apply方法

遇到如下形式的表达式时,apply方法就会被调用:
Object(参数1,参数2,…,参数N)。

通常,这样一个apply方法返回的是伴生类的对象
其作用是为了省略new关键字,
可以省略new关键字,根据自己的需要进行初始化。

apply方法必须写在伴生对象中。

//创建一个数组
scala> var myarray = Array(1,2,3)   ----> 使用了apply方法
	//myarray: Array[Int] = Array(1, 2, 3)
scala> //本质就是创建一个Array对象
scala> //省略了new关键字
object Student4{
  //定义自己的apply方法
  // 如果没有这个的apply方法,下面省略new的语句就会报错
  def apply(stuName:String)={
    new Student4(stuName)
  }
  def main(args: Array[String]): Unit = {
      var s5=new Student4("hello")
      println(s5.stuName)

    //由于省略关键字,创建这个对象的时候,就会在
    // object 找对应的apply方法
      var s=Student4("world")
      println(s.stuName)
  }
}

class Student4(val stuName:String) {
}

七、继承

1、跟Java一样,使用关键字extends
2、抽象类、抽象字段

例一:Person1类继承P1类

class P1(val name:String,val age:Int){
  def sayHello()="hello"
}

//override去覆盖父类的属性
class Person1( override val name:String,override val age: Int,val sex:String) extends P1 (name,age){

}

object p{
  def main(args: Array[String]): Unit = {
    var aa =new P1("hong",11)
    println(aa.name+":"+aa.age)

    var bb=new Person1("lan",21,"f")
    println(bb.sex)
    var cc=bb.sayHello()
    println(cc)
  }
}

例二:在子类中重写父类的方法

class Person1( override val name:String,override val age: Int,val sex:String) extends P1 (name,age){
//override去覆盖父类的方法,必须加
  override def sayHello()="world"
}

例三:使用匿名子类

//使用匿名子类去创建一个P1的对象,并重写P1的方法
    var t:P1=new P1("Jack",26){
      override def sayHello()="I am Jack"
    }    
    println(t.sayHello())

例四:使用抽象类(abstract)。抽象类中包含抽象方法,抽象类只能用来继承。

//有未实现的方法,所以为abstract修饰
abstract class Vehicle {
  def checkType():String
  def showName()
}

class Car extends Vehicle{
  override def checkType(): String = "123"

  override def showName(): Unit = {
    println("unknown")
  }
}

object Tets{
  def main(args: Array[String]): Unit = {
    var v1 = new Vehicle {
      override def checkType(): String = "bus"

      override def showName(): Unit = {
        println("byd")
      }
    }
    v1.showName()

    var v2 =new Car
    v2.showName()
  }
}

例五:使用抽象字段。抽象字段就是一个没有初始值的字段。

abstract class Vehicle {
  def checkType():String
  def showName()
  var id:Int
}

当去继承Vehicle的时候需要对抽象字段赋值。
抽象字段就是一个没有初始化的字段。

八、特质(trait)

类似Java中的抽象类,并且支持多重继承。
本质:就是抽象类,特点:支持多重继承。
trait就是抽象类。trait跟抽象类最大的区别:trait支持多重继承。

extends…with

trait Human {
  var id:Int
  var name:String
  def show():String

}

trait Action {

  def run():String
  def eat():String
}
trait Action1 {

  def fly():String

}
//多个Trait,用extends...with...with...
//提供主构造器
class Fireman(  var id:Int,  var name:String,val action:String) extends Human with Action with Action1 {
  override def show(): String = id+":"+name+":"+action
  override def run(): String = "run fast"
  override def eat(): String = "eat less"
  override def fly(): String = "cat not fly"
}

object Excute{
  def main(args: Array[String]): Unit = {
    var fireman=new Fireman(10,"xiaohua","run")
    println(fireman.show())
  }
}

九、包和包对象

9.1 包

Scala的包和Java中的包或者C++中的命名空间的目的是相同的:管理大型程序中的名称。
Scala中包的定义和使用:

  • 包的定义
  • 包的引入:Scala中依然使用import作为引用包的关键字
  • 而且Scala中的import可以写在任意地方(Java中,import写在最前面)

9.2 包对象

包可以包含类、对象和特质,但不能包含函数或者变量的定义。很不幸,这是Java虚拟机的局限。
把工具函数或者常量添加到包而不是某个Utils对象,这是更加合理的做法。
Scala中,包对象的出现正是为了解决这个局限。
Scala中的包对象:常量,变量,方法,类,对象,trait(特质),包。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值