Scala--面向对象

1. 什么是面向对象

  • 面向对象(Object Oriented)是软件开发方法,一种编程范式,面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。
  • 我们经常说Java是一种面向对象的语言,其中三大特性为:封装、继承、多态。

2. Scala class的使用

2.1 创建一个简单的类
class SimpleClass {

  val name: String = "spark"
  var age: Int = _

  def eat(): Unit = {
    println(s"$name eat")
  }
}
2.2 在Linux上面进行编译
[root@bigdatatest01 scala]# pwd
/root/script/scala
[root@bigdatatest01 scala]# vim SimpleClass.scala
class SimpleClass {

  val name: String = "spark"
  var age: Int = _

  def eat(): Unit = {
    println(s"$name eat")
  }
}

[root@bigdatatest01 scala]# scalac SimpleClass.scala 
[root@bigdatatest01 scala]# ls
SimpleClass.class  SimpleClass.scala
2.3 反编译Class
[root@bigdatatest01 scala]# javap -p SimpleClass.class 
Compiled from "SimpleClass.scala"
public class SimpleClass {
  private final java.lang.String name;
  public java.lang.String name();
  private int age;
  public int age();
  public void age_$eq(int);
  public void eat();
  public SimpleClass();
}
  • val name 对应private final java.lang.String name; public java.lang.String name();只能从这个类中得到name这个属性的数据,无法修改name 这个属性的数据。
  • var age:对应private int age; public int age(); public void age_$eq(int); 可以从此类中得到age数据,并且可以修改age数据。
2.4 SimpleClassApp Code
package com.xk.bigdata.scala.oo

object SimpleClassApp {

  def main(args: Array[String]): Unit = {
    val simpleClass = new SimpleClass
    simpleClass.age_$eq(16)
    println(s"${simpleClass.name}========>${simpleClass.age}")
    simpleClass.eat()
  }

}

class SimpleClass {

  val name: String = "spark"
  var age: Int = _

  def eat(): Unit = {
    println(s"$name eat")
  }
}
  • new $类名,调用的是此类的构造器,由于每个类都会默认一个空构造器,所以可以省略类名后面的括号。
  • 从上面反编译可以看出来, 对 象 . 对象. .属性_ e q ( eq( eq(数据)相当于Java中的set,可以把数据传输到这个对象的属性当中。

3. 构造器的使用

  • Scala中的构造器分为主构造器、附属构造器
  • 主构造器:定义方式:class $类名(val $属性名称: $属性类型),主构造器的定义是在Class后面来定义的,修饰符使用 val 来修饰,如果不使用 val 修饰符,对象则无法调用这个属性。
  • 附属构造器:def this($入参参数名: $入参参数类型),附属构造器一般是调用其他的附属构造器或者主构造器。
package com.xk.bigdata.scala.oo

object ConstructApp {

  def main(args: Array[String]): Unit = {
    val person = new Person("hadoop", 21, "A")
    println(person.school)
  }

  class Person(val name: String, val age: Int) {
    var school: String = _

    def this(name: String, age: Int, school: String) {
      this(name, age)
      this.school = school
    }
  }

}

4. 继承的使用

  • 在Scala中使用继承和Java中是一样,使用extends关键字,Java中Class只有单继承,接口可以多继承,而Scala中可以多继承,Scala 的trait 类似于Java中的接口,无论是trait还是子类,都是通过 extends + with 来实现,实现类或者接口数量大于三个,并且类或者trait通过先后顺序进行加载。
  • 如果需要重写父类的属性或者方法,需要在属性或者方法前面加上 override 关键字。
  • new 一个子类一定会先加载父类的构造器,然后加载子类的构造器。
package com.xk.bigdata.scala.oo

object ExtendsApp {

  def main(args: Array[String]): Unit = {
    val student = new Student("spark", 15, "A")
    student.eat()
    println(student.gender)
  }

  class Person(val name: String, val age: Int) {
    val gender = "M"

    def eat(): Unit = {
      println(s"Person Class $name........eat")
    }
  }

  class Student(name: String, age: Int, val school: String) extends Person(name, age) {

    override val gender: String = "L"

    override def eat(): Unit = {
      println(s"Student Class $name........eat")
    }
  }
}

5. 抽象类

  • 抽象类定义的时候需要有一个或者多个没有实现的方法,只是定义了方法,没有具体实现。
  • 抽象类只需要类名前面加 abstract 关键词,属性以及方法前面不需要添加 abstract 关键词。
  • 抽象类使用: 1) 显示定义 2)匿名子类
package com.xk.bigdata.scala.oo

object AbstractClassApp {

  def main(args: Array[String]): Unit = {
    // 通过显示定义子类
    val student = new Student("hadoop", 20)
    student.speak
    // 匿名子类
    val student2 = new Person("spark", 21) {
      override def speak: Unit = {
        println(s"$name is speak")
      }
    }
    student2.speak
  }

  abstract class Person(val name: String, val age: Int) {
    def speak: Unit
  }

  class Student(name: String, age: Int) extends Person(name, age) {
    override def speak: Unit = {
      println(s"$name is speak")
    }
  }

}

6. Trait

  • Scala 中 Trait 相当于Java中的接口,不同于接口的地方是,Trait 还可以定义属性和方法,一般情况下,Scala只能继承单一父类,但是可以继承多个 Trait,从结果来看,Scala实现了多重继承。
  • Trait 定义方式:使用 trait 关键词。
  • Trait 多重继承通过 extends 和 with 关键词来进行继承。
package com.xk.bigdata.scala.oo

object TraitApp {

  def main(args: Array[String]): Unit = {
    val miUSB = new MiUSB
    println(miUSB.name)
    miUSB.plugIn
    miUSB.insert
    miUSB.working
  }

  trait USB {
    println("========USB======")
    val name: String

    def insert

    def working

    def pop
  }

  trait Logger {
    println("========Logger======")

    def loginfo
  }

  trait Socket {
    println("========Socket======")

    def plugIn
  }

  class MiUSB extends Logger with USB with Socket {
    override def loginfo: Unit = {
      println("loginfo=====>MiUSB")
    }

    override val name: String = "小米充电器"

    override def insert: Unit = {
      println("接入充电器")
    }

    override def working: Unit = {
      println("充电器开始工作")
    }

    override def pop: Unit = {
      println("充电完成,拔出!!")
    }

    override def plugIn: Unit = {
      println("插上插座")
    }
  }

}

7. Case Class

  • Case Class 和 Class 的区别:
    • 初始化的时候可以不用new,也可以加上,但是普通类必须加new。
    • 默认实现了equals、hashCode方法。
    • 默认是可以序列化的,实现了Serializable。
    • 自动从scala.Product中继承一些函数。
    • case class 构造函数参数是public的,我们可以直接访问。
    • case class默认情况下不能修改属性值。
    • case class最重要的功能,支持模式匹配,这也是定义case class的重要原因
  • Case Class 和 Class 最大的区别就是 Case Class 重写了 equals、hashcode、tostring方法。
  • 重写 equals和hashcode 最大的表现就是两个属性值一样的对象是相等的,说明 Case Class 底层判断两个对象是否相等,判断的是对象里面的每个属性数据是否相等。
  • 重写 tostring 表现在 打印 Case Class 对象的时候打印出来的出现数据,打印 Class 对象的信息,打印的是内存地址。
  • 当使用 case class 的时候,Scala 会帮我们做如下几个事情:
    • 构造器中的参数如果不被声明为var的话,它默认的话是val类型的,但一般不推荐将构造器中的参数声明为var。
    • 自动创建伴生对象,同时在里面给我们实现子apply方法,使得我们在使用的时候可以不直接显示地new对象。
    • 伴生对象中同样会帮我们实现unapply方法,从而可以将case class应用于模式匹配。
    • 实现自己的toString、hashCode、copy、equals方法。
package com.xk.bigdata.scala.oo

object CaseClassApp {

  def main(args: Array[String]): Unit = {
    val person1 = new Person1("hadoop", 18)
    val person2 = new Person1("hadoop", 18)
    println(person1.toString)
    println(person1 == person2)
    val person3 = Person2("hadoop", 18)
    val person4 = Person2("hadoop", 18)
    println(person3.toString)
    println(person3 == person4)
  }

  class Person1(val name: String, val age: Int)

  case class Person2(name: String, age: Int)

}

8. Class 和 Object

  • Class 和 Object 的关系:
    • 对象不能带参数,类可以。
    • 对象可以和类名一样时,object被称为伴生对象,class被称为伴生类。
    • 类和伴生对象可以相互访问其私有属性,但是它们必须在一个源文件当中。
    • 类只会被编译,不会被执行。要执行,必须在Object中。
  • Class 和 Object 的区别:
    • Class 在调用的时候需要 new 一个对象,通过对象去调用Class里面的属性或方法。
    • Object 在调用的时候不需要 new 一个对象,可以直接调用 Object里面的属性和方法。
  • 同一个包下面的、名称相同的 Class 和 Object 互为伴生,Class为Object的伴生类, Object 为 Class 的伴生对象。
  • 在调用伴生对象的后面加上括号,相当于调用伴生对象里面的 apply 方法,通常可以在 apply 方法里面 new 一个伴生类。
  • 如果想一口气得到伴生类里面的所有属性,可以通过伴生对象的 unapply 方法来得到所有的属性。
package com.xk.bigdata.scala.oo

object ClassObjectApp {

  def main(args: Array[String]): Unit = {
    // 调用伴生类
    val person1 = new Person("hadoop", 21)
    person1.eat()
    // 调用伴生对象
    val person2 = Person("hadoop", 21)
    person2.eat()
    // 调用伴生对象的 unapply 方法
    val Person(name, age) = Person("hadoop", 21)
    println(s"name:$name==========age:$age")
  }

}

object Person {
  def apply(name: String, age: Int): Person = {
    println("调用 object Person 的 apply 方法")
    new Person(name, age)
  }

  def unapply(arg: Person): Option[(String, Int)] = {
    println("调用 object Person 的 unapply 方法")
    Option(arg.name, arg.age)
  }
}

class Person(val name: String, val age: Int) {
  def eat(): Unit = {
    println(s"$name is eat")
  }
}

9. Case Class 和 Case Object

  • Case Class 、 Case Object 的区别:
    • 类中有参和无参,当类有参数的时候,用case class ,当类没有参数的时候那么用case object。
package com.xk.bigdata.scala.oo

object CaseClassCaseObjectApp {
  def main(args: Array[String]): Unit = {
    // 调用 case class eat
    val person1 = new Per("hadoop", 18)
    person1.eat()
    // 调用 case object eat
    Per.eat()
  }
}

case class Per(name: String, age: Int) {
  def eat(): Unit = {
    println("case class Person eat")
    println(s"$name is eat")
  }
}

case object Per {
  def eat(): Unit = {
    println("case object Person eat")
    println("eat")
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值