【Scala】类和对象的介绍与使用

目录

类和对象

创建类和对象

定义和访问成员变量

使用下划线初始化成员变量

定义成员方法

访问修饰符

类的构造器

主构造器

辅助构造器

单例对象

在单例对象中定义成员方法

main方法

实现App Trait来定义入口

伴生对象

private[this]访问权限

继承

override和super

类型判断

isInstanceOf/asInstanceOf

getClass/classOf

抽象类

匿名内部类

特质(trait)

继承单个特质

继承多个特质

object继承trait

使用trait实现模板模式

对象混入trait

trait实现调用链模式

trait继承class

样例类

常用方法

样例对象


  • 类和对象

scala是支持面向对象的,也有类和对象的概念。我们依然可以基于scala语言来开发面向对象的应用程序。

 

 

  • 创建类和对象

使用class来定义一个类 new来创建对象

 

例:

object demo01 {

  //创建类
  class user{}
  
  def main(args: Array[String]): Unit = {
      //创建对象
      var u = new user()
      println("hello word")
  }
}

 

  • 定义和访问成员变量

一个类会有自己的属性,例如:人这样一个类,有自己的姓名和年龄。在类中定义、和访问成员变量

 

例:

object demo01 {
  //创建类
  class user{
    // 定义成员变量
    val id = "123"
    var name = ""
    var age = 0
  }

  def main(args: Array[String]): Unit = {
      //创建对象
      var u = new user()
      u.name = "zhangsan"
      u.age = 20

      //获取变量值
      println(u.id)
      println(u.name)
      println(u.age)
  }
}

 

  • 使用下划线初始化成员变量

1.在定义var类型的成员变量时,可以使用_来初始化成员变量

2.使用下划线初始化,成员变量必须为var(变量),并且要指定数据类型

 

例:

object demo01 {

  //创建类
  class user{
    // 定义成员变量 使用下划线进行初始化
    var id:String =  _
    var name:String = _
    var age:Int = _
  }

  def main(args: Array[String]): Unit = {
      //创建对象
      var u = new user()
      u.name = "zhangsan"
      u.age = 20

      //获取变量值
      println(u.id)
      println(u.name)
      println(u.age)
  }
}

 

  • 定义成员方法

类可以有自己的行为,scala中也可以通过定义成员方法来定义类的行为。使用def来定义成员方法

 

例:

object demo01 {
  //创建类
  class user{
    // 定义成员变量 使用下划线进行初始化
    var id:String =  _
    var name:String = _
    var age:Int = _

    //定义成员方法
    def prints (msg:String): Unit = {
      println(msg + " hello")
    }
  }

  def main(args: Array[String]): Unit = {
      //创建对象
      var u = new user()
      u.name = "zhangsan"
      u.age = 20
    
      //输出成员方法
       u.prints("zhangsan")
  }
}

 

  • 访问修饰符

1.和Java一样,scala也可以通过访问修饰符,来控制成员变量和成员方法是否可以被访问。

2.可以在成员前面添加private/protected(私有的/受保护的)关键字来控制成员的可见性。

3.scala中,没有public关键字,任何没有被标为private或protected的成员都是公共的

 

例:

object demo02 {
  class Persion {
    //定义成变量
    private var name: String = ""
    private var age: Int = 0

    //定义成员方法
    def getName() = {
      this.name
    }

    def setName(name: String): Unit = {
      this.name = name
    }

    def getAge() = {
      this.age
    }

    def setAge(age: Int): Unit = {
      this.age = age
    }

    private def getNameAndAge() = {
      this.getName() + "  " + this.getAge()
    }

  }
  
  def main(args: Array[String]): Unit = {
    //实例化对象
    var persion = new Persion();

    //调用方法
    persion.setName("zhangsan")
    persion.setAge(200)

    println(persion.getName())
    println(persion.getAge())
  }
}

 

  • 类的构造器

1.当创建类对象的时候,会自动调用类的构造器。之前使用的都是默认构造器

2.Scala的构造器分为主构造器与辅助构造器

3.主构造器:直接在class括号内添加属性

4.辅助构造器:除了主构造器之外的都是辅助构造器

 

主构造器

1.主构造器的参数列表是直接定义在类名后面,添加了val/var表示直接通过主构造器定义成员变量

2.构造器参数列表可以指定默认值

3.创建实例,调用构造器可以指定字段进行初始化

4.整个class中除了字段定义和方法定义的代码都是构造代码

格式:

class 类名(var/val 参数名:类型 = 默认值, var/val 参数名:类型 = 默认值){
   // 构造代码块
}

例:

object demo03 {
  //创建构造器
  class Person(var name:String = "",var age:Int = 0){

  }

  def main(args: Array[String]): Unit = {
    var p = new Person("zhangsan",17)
    println(p.name)
    println(p.age)
  }
}

 

辅助构造器

1.除了主构造器之外的构造器称为辅助构造器。

2.定义辅助构造器与定义方法一样,也使用def关键字来定义

3.这个方法的名字为this

4.辅助构造器的第一行代码,必须要调用主构造器或者其他辅助构造器

格式:

def this(参数名:类型, 参数名:类型) {
    // 第一行需要调用主构造器或者其他构造器
    // 构造器代码
}

例:

object demo03 {
  //创建构造器
  class Person(var name:String = "",var address:String =  ""){

      //创建辅助构造器
      def this(arr:Array[String]){
        this(arr(0),arr(1))
      }
  }

  def main(args: Array[String]): Unit = {
      //实例化对象
      var p = new Person(Array("zhangsan","北京"))
      println(p.name)
      println(p.address)
  }
}

 

  • 单例对象

1.scala中没有Java中的静态成员,若想要定义类似于Java的static变量、static方法,就要使用到scala中的单例对象——object.

2.单例对象表示全局仅有一个对象(类似于Java static概念)

3.定义单例对象和定义类很像,就是把class换成object

4.在object中定义的成员变量类似于Java的静态变量

5.可以使用object直接引用成员变量

 

例:

object demo04 {
  //创建单例对象
  object Person {
    var name: String = "zhangsan"
  }

  def main(args: Array[String]): Unit = {
    println(Person.name)
  }
}

 

在单例对象中定义成员方法

1.在object中定义的成员方法类似于Java的静态方法

例:

object demo04 {
  //创建单例对象
  object Person {
    var name: String = "zhangsan"

    //定义成员方法
    def show() = {
      println("show")
    }
  }

  def main(args: Array[String]): Unit = {
    println(Person.name)

    //调用方法
    Person.show()
  }
}

 

  • main方法

scala和Java一样,如果要运行一个程序,必须有一个main方法。在Java中main方法是静态的,而在scala中没有静态方法。在scala中,这个main方法必须放在一个单例对象中。

 

格式:

def main(args:Array[String]):Unit = {
    // 方法体
}

 

实现App Trait来定义入口

创建一个object,继承自App Trait(特质),然后将需要编写在main方法中的代码,写在object的构造方法体内。

 格式:

object 单例对象名 extends App {
    // 方法体
}

例:

object demo05 extends App {
    println("holle")
}

 

  • 伴生对象

1.一个class和object具有同样的名字。这个object称为伴生对象,这个class称为伴生类

2.伴生对象必须要和伴生类一样的名字

3.伴生对象和伴生类在同一个scala源文件中

4.伴生对象和伴生类可以互相访问private属性

 

例:

object demo06 {
  class Person{
    private val id:String = "123"

    //可以互相访问私有数据
    println(Person.name)
  }

  object Person{
    private var name:String = "zhangsan"

    //可以互相访问私有数据
    println(new Person().id)
  }

  def main(args: Array[String]): Unit = {

  }
}

 

private[this]访问权限

如果某个成员的权限设置为private[this],表示只能在当前类中访问。伴生对象也不可以访问

例:

object demo06 {
  class Person{
    private[this] val id:String = "123"

    //可以互相访问私有数据
    println(Person.name)
  }

  object Person{
    private var name:String = "zhangsan"

    //被private[this]修饰 不能访问 报错 
    //println(new Person().id)
  }

  def main(args: Array[String]): Unit = {

  }
}

 

  • 继承

1.scala语言是支持面向对象编程的, 可以使用scala来实现继承,通过继承来减少重复代码

2.使用extends关键字来实现继承

3.可以在子类中定义父类中没有的字段和方法,或者重写父类的方法

4.类和单例对象都可以从某个父类继承

 

格式:

class/object 子类 extends 父类 {
    ..
}

 

例:

//父类
class Person {
  var name:String = "zhangsan"
  def getName(): Unit ={
    this.name
  }
}

object demo07 {
    //子类
    class  Stu extends Person{

    }

  def main(args: Array[String]): Unit = {
    var stu = new Stu();
    //调用父类的方法
    println(stu.name)
  }
}

 

  • override和super

1.类似于Java语言, 在子类中使用override需要来重写父类的成员,可以使用super来引用父类

2.子类要覆盖父类中的一个方法,必须要使用override关键字

3.使用override来重写一个val字段

4.使用super关键字来访问父类的成员方法

 

例:

//父类
class Person {
  val name = "super"
  def getName = name
}

object demo07 {

  class Student extends Person {
    // 重写val字段
    override val name: String = "child"
    // 重写getName方法
    override def getName: String = "hello, " + super.getName
  }


  def main(args: Array[String]): Unit = {
    var stu = new Student();
    println(stu.name)
    println(stu.getName)
  }
}

 

 

  • 类型判断

有时候,我们设计的程序,要根据变量的类型来执行对应的逻辑

 

 

isInstanceOf/asInstanceOf

1.isInstanceOf判断对象是否为指定类以及其子类的对象

2.asInstanceOf将对象转换为指定类型

格式:

// 判断对象是否为指定类型
val trueOrFalse:Boolean = 对象.isInstanceOf[类型]

// 将对象转换为指定类型
val 变量 = 对象.asInstanceOf[类型]

例:

//父类
class Person {
  val name = "super"
  def getName = name
}

object demo07 {

    //子类
  class Student extends Person {
    // 重写val字段
    override val name: String = "child"
    // 重写getName方法
    override def getName: String = "hello, " + super.getName
  }


  def main(args: Array[String]): Unit = {
      var stu1 = new Student();
      var stu2:Person = new Student();

      //判断对象是否为指定类型 true
      println(stu1.isInstanceOf[Student])

      //将对象转换为指定类型 将Person类型转为Student类型
      if (stu2.isInstanceOf[Student]){
        val s2 = stu2.asInstanceOf[Student]
        println(s2)
      }

  }
}

 

getClass/classOf

1.isInstanceOf 只能判断对象是否为指定类以及其子类的对象,而不能精确的判断出,对象就是指定类的对象。如果要求精确地判断出对象就是指定类的对象,那么就只能使用 getClass 和 classOf 。

2.p.getClass可以精确获取对象的类型(不是父类)

3.classOf[x] 可以指定精确类型

4.使用==操作符可以直接比较类型

例:

class Person {
  val name = "super"
  def getName = name
}

object demo07 {

  class Student extends Person {
    // 重写val字段
    override val name: String = "child"
    // 重写getName方法
    override def getName: String = "hello, " + super.getName
  }


  def main(args: Array[String]): Unit = {
      var stu = new Student();

      //true
      println(stu.getClass() == classOf[Student])

      //false//抽象类
abstract class Shape {
  //抽象字段
  var r:Double

  //抽象方法
  def area(): Double
}

//子类1 正方形
class Square(edge: Double) extends Shape {
  //实现字段
  override var r: Double =  edge;

  //实现方法
  override def area(): Double = {
    r * r
  }

}

//子类2 圆形
class Roundness(radius: Double) extends Shape {
  //实现字段
  override var r: Double = radius

  //实现方法
  override def area(): Double = {
    r * r * 3.14
  }

}

def main(args: Array[String]): Unit = {
  //正方形
  var square = new Square(10);
  println(square.area())

  //圆形
  var roundness = new Roundness(10);
  println(roundness.area())

}
      println(stu.getClass() == classOf[Person])
  }
}

 

  • 抽象类

1.如果类的某个成员在当前类中的定义是不包含完整的,它就是一个抽象类

2.不完整定义有两种情况:

                                         a.方法没有方法体(抽象方法)

                                         b.变量没有初始化(抽象字段)

3.定义抽象类和Java一样,在类前面加上abstract关键字

4.在抽象类中不抽象的字段或方法不用重写

 

格式:

// 定义抽象类
abstract class 抽象类名 {
  // 定义抽象字段
  val 抽象字段名:类型
  // 定义抽象方法
  def 方法名(参数:参数类型,参数:参数类型...):返回类型
}

 

例:

//抽象类
abstract class Person {
  //抽象字段
  var name: String
  //抽象方法
  def Say(msg:String):String
}
//抽象类
abstract class Shape {
  //抽象字段
  var r:Double

  //抽象方法
  def area(): Double
}

//子类1 正方形
class Square(edge: Double) extends Shape {
  //实现字段
  override var r: Double =  edge;

  //实现方法
  override def area(): Double = {
    r * r
  }

}

//子类2 圆形
class Roundness(radius: Double) extends Shape {
  //实现字段
  override var r: Double = radius

  //实现方法
  override def area(): Double = {
    r * r * 3.14
  }

}

//main方法
def main(args: Array[String]): Unit = {
  //正方形
  var square = new Square(10);
  println(square.area())

  //圆形
  var roundness = new Roundness(10);
  println(roundness.area())

}

 

  • 匿名内部类

匿名内部类是没有名称的子类,直接用来创建实例对象。Spark的源代码中有大量使用到匿名内部类。scala中的匿名内部类使用与Java一致。

 

格式:

val/var 变量名 = new 类/抽象类 {
    // 重写方法
}

 

例:

//抽象类
abstract class Shape {
  //抽象字段
  var r: Double

  //抽象方法
  def area(): Double
}

//main方法
def main(args: Array[String]): Unit = {

    //匿名内部类
    var dd = new Shape {
      //重写字段
      override var r: Double = 10
      //重写方法
      override def area(): Double = {
          r
      }
    }

    //打印
    println(dd.area)
    
  }
}

 

  • 特质(trait)

1.scala中没有Java中的接口(interface),替代的概念是特质

2.特质是scala中代码复用的基础单元

3.它可以将方法和字段定义封装起来,然后添加到类中

4.与类继承不一样的是,类继承要求每个类都只能继承一个超类,而一个类可以添加任意数量的特质。

5.特质的定义和抽象类的定义很像,但它是使用trait关键字

6.使用extends来继承trait(scala不论是类还是特质,都是使用extends关键字)

7.如果要继承多个trait,则使用with关键字

8.在trait中可以定义具体字段和抽象字段

9.scala中可以将trait混入到对象中,就是将trait中定义的方法、字段添加到一个对象中

10.trait也可以继承class的。特质会将class中的成员都继承下来

 

格式:

//定义特质
trait 名称 {
    // 抽象字段
    // 抽象方法
}

//继承特质
class 类 extends 特质1 with 特质2 {
    // 字段实现
    // 方法实现
}

 

继承单个特质

例:

//特质
trait Person {
  //完整字段 不需要被继承
  var id: String = "123456"

  //抽象字段
  var name: String

  //完整方法 不需要被继承
  def SayHello(msg: String) = {
    println(msg)
  }

  //抽象方法
  def Say(): String


}

//子类
class Stuent extends Person {
  //实现父类字段
  override var name: String = "张三"
  //实现父类方法
  override def Say(): String = {
    name
  }
}

 

继承多个特质

例:

//特质1
trait Person1 {
  //完整字段 不需要被继承
  var id: String = "123456"

  //抽象字段
  var name: String

  //完整方法 不需要被继承
  def SayHello(msg: String) = {
    println(msg)
  }

  //抽象方法
  def Say(): String
}

//特质2
trait Person2 {
  //抽象方法
  def doing(): String
}

//子类 继承Person1 Person2两个特质
class Student extends Person1 with Person2 {
  //实现父类Person1字段
  override var name: String = "张三"

  //实现父类Person1方法
  override def Say(): String = {
    name
  }

  //实现父类Person2方法
  override def doing(): String = {
    name
  }
}

 

object继承trait

例:

//特质
trait Sum2 {
  //抽象方法
  def sum(num1: Int, num2: Int): Unit
}

//子object
object Sums extends Sum2 {
   //重写方法
  override def sum(num1: Int, num2: Int): Unit = {
    println(num1 + num2)
  }
}

//main方法
def main(args: Array[String]): Unit = {
  //调用方法  
  Sums.sum(10,10)
}

 

使用trait实现模板模式

在一个特质中,具体方法依赖于抽象方法,而抽象方法可以放到继承trait的子类中实现,这种设计方式也称为模板模式

例:

//特质
trait Logger {
  //抽象方法
  def log(msg: String): Unit

  //创建具体方法并调用抽象方法
  def info(msg: String) = log("Info" + msg)
  def warn(msg: String) = log("Warn" + msg)
  def error(msg: String) = log("Error" + msg)

}

//继承特质
class ConsoleLogger extends Logger {

  //现抽象方法
  override def log(msg: String): Unit = {
    println(msg)
  }
}

def main(args: Array[String]): Unit = {
  var log =  new ConsoleLogger();

  //调用方法
  log.info("信息日志")
  log.warn("警告日志")
  log.error("错误日志")
}

 

对象混入trait

scala中可以将trait混入到对象中,就是将trait中定义的方法、字段添加到一个对象中

格式:

val/var 对象名 = new 类 with 

例:

//特质
trait Do {
  def say(msg: String): String = {
    println(msg + "1")
    msg
  }

  def say1():String
}

//类
class Student

//main方法
def main(args: Array[String]): Unit = {
  //创建对象 混入trait
  var stu = new Student() with Do {
    //实现抽象方法
    override def say1(): String = {
      "lisi"
    }
  }

  //调用方法
  stu.say("zhangsan")
  println( stu.say1())
}

 

trait实现调用链模式

类继承了多个trait后,可以依次调用多个trait中的同一个方法,只要让多个trait中的同一个方法在最后都依次执行super关键字即可。类中调用多个tait中都有这个方法时,首先会从最右边的trait方法开始执行,然后依次往左执行,形成一个调用链条。

例:

//特质1
trait HandlerTrait {

  def handler(msg: String) = {
    println("第四步:打印数据" + msg)
  }

}

//特质2 继承特质1
trait DataValidHandlerTrait extends HandlerTrait {

  //重写方法
  override def handler(msg: String): Unit = {
    println("第三步:验证数据" + msg)

    //调用父类方法
    super.handler(msg)
  }

}

//特质3 继承特质1
trait SignatureValidHandlerTrait extends HandlerTrait {

  //重写方法
  override def handler(msg: String): Unit = {
    println("第二步:检查签名" + msg)

    //调用父类方法
    super.handler(msg)
  }

}

//子类 继承特质1 特质2
class PaymentService extends DataValidHandlerTrait with SignatureValidHandlerTrait {
  def pay(msg: String) = {
    println("第一步:准备支付" + msg)
    super.handler(msg)
  }
}

//main方法
def main(args: Array[String]): Unit = {
  var paymentService = new PaymentService();
  paymentService.pay("牛奶")
}

 

trait继承class

trait也可以继承class的。特质会将class中的成员都继承下来

//父类
class MyUtils {
  def printMsg(msg: String) = {
    println(msg)
  }

}

//子特质
trait Logger extends MyUtils {
  def log(msg: String) = printMsg(msg)
  
}

//特质的子类
class Person extends Logger {
  def Say(msg: String) = log(msg)
  
}

//main方法
def main(args: Array[String]): Unit = {
  var person = new Person();

  //调用方法  Person子类可以调用父类所有方法
  person.Say("zhangsan");
  person.log("lisi")
  person.printMsg("wangwu")
}

 

  • 样例类

样例类是一种特殊类,它可以用来快速定义一个用于保存数据的类(类似于Java POJO类),在后续要学习并发编程和spark、flink这些框架也都会经常使用它。

 

格式:

case class 样例类名([var/val] 成员变量名1:类型1, 成员变量名2:类型2, 成员变量名3:类型3)

 

例:

//样例类  默认的字段为常量
case class Student(var name: String, age: Int) {

}

//main方法
def main(args: Array[String]): Unit = {

  //创建样例类对象 不需要new
  var student = Student("张三", 17)

  //重赋值数据 如果数据为变量(var)则可以重新赋值
  student.name = "李四"

  //打印数据
  println(student.name)
  println(student.age)
}

 

常用方法

apply:apply方法可以让我们快速地使用类名来创建对象

toString:toString返回样例类名称(成员变量1, 成员变量2, 成员变量3....)

equals:样例类自动实现了equals方法,可以直接使用==比较两个样例类是否相等,即所有的成员变量是否相等

hashCode:样例类自动实现了hashCode方法,如果所有成员变量的值相同,则hash值相同,只要有一个不一样,则hash值不一样。

copy:样例类实现了copy方法,可以快速创建一个相同的实例对象,可以使用带名参数指定给成员进行重新赋值

 

  • 样例对象

1.定义枚举

2.作为没有任何参数的消息传递

 

格式:

case object 样例对象名

 

例:

object Test02 {
  //特质
  trait sex

  //定义特质的枚举
  case object Boy extends sex

  case object Girl extends sex

  //创建对象 对象的一个属性设置为枚举
  case class Person(name: String, sex: sex)

  def main(args: Array[String]): Unit = {
    //创建对象
    var person = Person("张三", Boy)
  }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值