Scala 面向对象编程中级

面向对象编程中级
  • 抽象
  • 封装
  • 继承
  • 重写
  • 类型检查和转换
 
1.包
1.1 包/作用域
    在Java和Scala中管理项目可以使用包结构,C和C#使用命名空间,对于package,有如下几种形式。
package com.nick.impatient.people
class Person{
  val name = "Nick"
  def play(message: String): Unit ={
  }
}

// 等同于:
package com.nick.impatient
package people
class Person{
  val name = "Nick"
  def play(message: String): Unit ={
  }
}

//等同于:
package com.nick.impatient{
  package people{
    class Person{
      val name = "Nick"
      def play(message: String): Unit ={
      }
    }
  }
}

//  说明:
//(1)包也可以像内部类那样嵌套,作用域原则:可以直接向上访问。即,子package中直接访问父package中的内容。(即:作用域)
//(2)包对象可以持有函数和变量
//(3)引入语句可以引入包、类和对象
//(4)源文件的目录和包之间并没有强制的关联关系
//(5)可以在同一个.scala文件中,声明多个并列的package
//(6)包名可以相对也可以绝对,比如,访问ArrayBuffer的绝对路径是:_root_.scala.collection.mutable.ArrayBuffer
1.2 包对象    包可以包含类、对象和特质trait,但不能包含函数或变量的定义。很不幸,这是Java虚拟机的局限。把工具函数或常量添加到包而不是某个Utils对象,这是更加合理的做法。包对象的出现正是为了解决这个局限。每个包都可以有一个包对象。你需要在父包中定义它,且名称与子包一样。
package com.nick.impatient
package object people {
  val defaultName = "Nick"
}
package people {
  class Person {
    var name = defaultName
  }
}

1.3 包可见性

// 在Java中,没有被声明为public、private或protected的类成员在包含该类的包中可见。在Scala中,你可以通过修饰符达到同样的效果。以下方法在它自己的包中可见:
package com.nick.impatient.people
class Person {
  private[people] def description="人的名字:" + name
}
// 当然,也可以将可见度延展到上层包:
private[impatient] def description="人的名字:" + name

1.4 引入

    Scala 引入包也是使用 import, 基本的原理和机制和 Java 一样,但是 Scala 中的 import 功能更加强 大,也更灵活。
Scala 引入包的细节和注意事项
    1) 在 Scala 中,import 语句可以出现在任何地方,并不仅限于文件顶部,import 语句的作用一直 延伸到包含该语句的块末尾。这种语法的好处是:在需要时在引入包,缩小 import 包的作用范围,提高效率。
    2) Java 中如果想要导入包中所有的类,可以通过通配符*,Scala 中采用下 _
    3) 如果不想要某个包中全部的类,而是其中的几个类,可以采用选取器(大括号)
    4) 如果引入的多个包中含有相同的类,那么可以将不需要的类进行重命名进行区分,这个就是重命名。
    5) 如果某个冲突的类根本就不会用到,那么这个类可以直接隐藏掉。
 
2.抽象
    我们在前面去定义一个结构体的时候,实际上就是把一类事物的共有的属性(字段)和行为(方法)提取出来,形成一个物理模型(模板)。这种研究问题的方法称为抽象。
object Scala01_BankDemo {
  def main(args: Array[String]): Unit = {
    //开卡
    val account = new Account("gh00001",1000,"111111")
    account.query("111111")
    account.withDraw("111111", 100)
    account.query("111111")
  }
}


//编写一个Account类
class Account(inAccount: String, inBalance: Double, inPwd: String) {
/*
  属性:账号、余额、密码
  方法:查询、取款、存款
*/
  private val accountNo = inAccount
  private var balance = inBalance
  private var pwd = inPwd


  //查询
  def query(pwd: String): Unit = {
    if (!this.pwd.equals(pwd)) {
      println("密码错误")
      return
    }
    printf("账号为%s 当前余额是%.2f\n", this.accountNo, this.balance)
  }


  //取款
  def withDraw(pwd:String,money:Double): Any = {
    if (!this.pwd.equals(pwd)) {
      println("密码错误")
      return
    }
    //判断money是否合理
    if (this.balance < money) {
      println("余额不足")
      return
    }
    this.balance -= money
    money
  }
}

2.1 抽象类

    在 Scala 中,通过 abstract 关键字标记不能被实例化的类。方法不用标记 abstract,只要省掉方法体即可。抽象类可以拥有抽象字段,抽象字段/属性就是没有初始值的字段。
object AbstractDemo01 {
  def main(args: Array[String]): Unit = {
    println("xxx")
  }
}

//抽象类
abstract class Animal{
  var name : String //抽象的字段
  var age : Int // 抽象的字段
  var color : String = "black" //普通属性
  def cry() //抽象方法,不需要标记 abstract
}

// Scala 抽象类使用的注意事项和细节讨论 
1) 抽象类不能被实例
2) 抽象类不一定要包含 abstract 方法。也就是说,抽象类可以没有 abstract 方法
3) 一旦类包含了抽象方法或者抽象属性,则这个类必须声明为 abstract
4) 抽象方法不能有主体,不允许使用 abstract 修饰
5) 如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法和抽象属性,除非它自己也声明为 abstract 类
6) 抽象方法和抽象属性不能使用 private、final 来修饰,因为这些关键字都是和重写实现相违背的 
7) 抽象类中可以有实现的方法.
8) 子类重写抽象方法不需要 override,写上也不会错.
3.封装
    封装(encapsulation)就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作。
3.1 封装的理解和好处
    1) 隐藏实现细节
    2) 提可以对数据进行验证,保证安全合理ScalaBaseConstrator
    3) 同时可以加入业务逻辑
3.2 如何体现封装
    1) 对类中的属性进行封装
    2) 通过成员方法,包实现封装
3.3 封装的实现步骤
    1) 将属性进行私有化
    2) 提供一个公共的 set 方法,用于对属性判断并赋值
    3) 提供一个公共的 get 方法,用于获取属性的值
 
4.继承
    继承可以解决代码复用,让我们的编程更加靠近人类思维.当多个类存在相同的属性(变量)和方法时, 可以从这些类中抽象出父类(比如 Student),在父类中定义这些相同的属性和方法,所有的子类不需要重 新定义这些属性和方法,只需要通过 extends 语句来声明继承父类即可。    和 Java 一样,Scala 也支持类的单继承
object Scala02_Extends {
    def main(args: Array[String]): Unit = {
      //使用
      val student = new Student
      student.name = "jack" //调用了 student.name() //调用到从 Person 继承的 name() student.studying()
      student.showInfo()
    }
}

class Person {
   var name : String = _
   var age : Int = _
    def showInfo(): Unit = {
      println("学生信息如下:")
      println("名字:" + this.name)
    }
}

//Student 类继承 Person
class Student extends Person {
  def studying(): Unit = { //这里可以使用父类的属性 println(this.name + "学习 scala 中....")
  }
}
5.重写
    override是覆盖的意思,在很多语言中都有,在scala中,override是非常常见的,在类继承方面,它和java不一样,不是可写可不写的了,而是必须写的。如果不写而覆盖了对应的属性或者方法的话,编译器就会报错了。
object Scala03_FiledOverrideDetail {
  def main(args: Array[String]): Unit = {
    val bbbb = new BBBB
  }
}


class AAAA {
  val name: String = "" 
}


class BBBB extends AAAA {
  override val name: String = "jj" 
}
6.类型检查和转换
    要测试某个对象是否属于某个给定的类,可以用 isInstanceOf 方法。用 isInstanceOf 方法将引用转换为子类的引用。classOf 获取对象的类名。
    classOf[String]就如同 Java 的 String.class 。
    obj.isInstanceOf[T]就如同 Java 的 obj instanceof T 判断 obj 是不是 T 类型。 obj.asInstanceOf[T]就如同 Java 的(T)obj 将 obj 强转成 T 类型。
object Scala04_TypeConvert {  
  def main(args: Array[String]): Unit = {
  //ClassOf的使用,可以得到类名
  println(classOf[String]) // 输出
  val s = "king"
  println(s.getClass.getName) //使用反射机制


  //isInstanceOf asInstanceOf
  var p1 = new Person200
  var emp = new Emp200
  //将子类引用给父类(向上转型,自动)
  p1 = emp
  //将父类的引用重新转成子类引用(多态),即向下转型
  var  emp2 = p1.asInstanceOf[Emp200]
  emp2.sayHello()
  }
}


//Person类
class Person200 {
  var name: String = "tom"
  def printName() { //输出名字
    println("Person printName() " + name)
  }
  def sayHi(): Unit = {
    println("sayHi...")
  }
}


//这里我们继承Person
class Emp200 extends Person200 {
  //这里需要显式的使用override
  override def printName() {
    println("Emp printName() " + name)
    //在子类中需要去调用父类的方法,使用super
    super.printName()
    sayHi()
  }
  def sayHello(): Unit = {
  }
}

//说明:类型检查和转换的最大价值在于:可以判断传入对象的类型,然后转成对应的子类对象,进行相关操作,这里也体现出多态的特点。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员学习圈

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值