Scala(五)-①-面相对象中级-抽象-封装、继承、多态

前言

面相对象程序设计有四大要素, 抽象封装继承多态

① 抽象

①-① Why

抽象是为了什么?

一句话,抽象是为了分门别类.这样才能隔离问题中的关注点,降低研究问题的复杂度.

程序设计中我们为什么要学习抽象?

程序设计中也需要分门别类,OOP就是基于抽象之上构建.比如你要理解封装,就要知道抽象的意义,封装只不过是抽象概念上进行加强.更细致的划分了方法的访问权限

①-② How

语法和规则
  • 抽取公共的属性
  • 抽取公共的行为为方法

如下图,我们可以抽象出动物的概念

image.png
用代码表示抽象出的动物
class Animal(inColor :String, inAge :Int, inWeight :Int) {
    
    var color :String = inColor
    var age :Int = inAge
    var weight :Int = inWeight
    
    def eat() {
        
    }
    
}

①-③ What

抽象概念的本质就是分门别类,抽取共性,形成概念.

② 封装

②-① Why

OOP编程中,我们经常需要隐藏实现细节,对数据进行校验,保证数据的合法性.这时候就需要用到封装这个特性.

②-② How

语法和规则
  • 将属性进行私有化
  • 提供一个公共的set方法,用于对属性判断并赋值
def  setXxx(参数名 : 类型) : Unit = {
        //加入数据验证的业务逻辑
        属性 = 参数名   
}
  • 提供一个公共的get方法,用于获取属性的值
def getXxx() : 返回类型 = {
    return 属性
}
Demo
object EncapDemo {
  def main(args: Array[String]): Unit = {

    val stu = new Student
    stu.setScore(120)
    println(s"student score = ${stu.score}")
  }
}

class Student {

  var score : Double = 0.0

  def setScore(inScore :Double): Unit = {
    if (inScore > 100) score = 100
    else if (inScore < 0 ) score = 0
    else score = inScore
  }

}

②-③ What

封装就是分析出类,将抽象出来的属性和方法放在一个类里,暴露该暴露的接口,过滤和校验相应的输入数据,隐藏内部的复杂性, 这就是封装.

②-④ Details

  • Scala中声明属性的时候就会生成和setter和getter功能一样的方法,只是不符合JavaBean规范.setter-> 属性名_$eq(xxx) , getter->属性名()
  • scala中可以直接使用点号访问属性,其本质是调用对应的setter和getter方法.(setter-> 属性名_$eq(xxx) , getter->属性名())
  • 所以现在很多框架,因为上面的这个特性,可以直接对属性进行反射.

③ 继承

③-① Why

继承主要为了解决代码复用的问题,提现的是别人有,我拿来用的理念.

③-② How

规则和语法
class 子类名 extends 父类名 {
    // 类体
}
Demo

演示Student类继承Person类,并添加study方法表示学生的学习行为

object ExtendsDemo {

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

    val stu = new Student("lisi", 25)
    stu.showInfo()
    stu.study()


  }

}


class Person(inName :String, inAge :Int) {

  var name :String = inName
  var age :Int = inAge

  def showInfo(): Unit = {
    println(s"name = ${name}, age = ${age}")
  }
}

class Student(inName :String, inAge :Int) extends Person(inName : String, inAge :Int) {


  def study(): Unit = {

    println(s"${name} studing")
  }
}

③-③ What

  • 继承本质逻辑上说是is-a的关系.我们对现实世界的认知,依赖于我们给事物们取的“名字”,有了这些名字,人类对世界的思考以及交流才变得可能,这些名字,有着抽象度大小的区别,例如赤兔马,既是马,也是动物.

③-④Details

  • 开发中要慎用继承,多用组合,组合也能复用别人的代码,而且不像继承耦合得太深(父类一变,只类就会受影响,这个影响可能是几千个类).
  • 子类继承父类所有属性和方法.能不能访问则看权限修饰
  • scala规定, 重写父类一个非抽象方法需要用override修饰符,调用超类的方法使用super
    在Student类中增加如下方法和成员变量
  var address :String = inAddress

  override def showInfo() {
    println(s"name = ${name}, age = ${age} address=${address}")
  }
  • 测试某个对象是否属于某个给定的类,可以用isInstanceOf方法.asInstanceOf方法将引用转换为子类的引用.classOf获取对象的类名.
object ExtendsDemo2 {

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

    println(classOf[String])                // 等价于String.class

    println("Hello".isInstanceOf[String])   // 等价于isInstanceOf(object)

    val stu = new Student("lisi", 23, "beijing")
    stu.study()
    val person = stu.asInstanceOf[Person]   // 等价于(Person)stu
    person.showInfo()

  }
}
  • Scala中超类的构造.(类有一个主构器和任意数量的辅助构造器,而每个辅助构造器都必会调用到主构造器,可以是间接也可以是直接)
object ExtendsDemo3 {

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

    val son = new Son("weipeng")

  }

}

class Parent {
  var name :String = _
  println("parent Constructor")
}

class Son() extends Parent() {

  println("son primary Constructor")

  def this(inName :String) {
    this
    this.name = inName
    println("son sub Constructor")
  }
}

打印输出

parent Constructor
son primary Constructor
son sub Constructor
  • Scala中的复写字段.Java中不可以复写字段,旦Scale中支持对字段的复写.
  • def只能重写另一个def(即:方法只能重写另一个方法)
  • var只能重写另一个抽象的var属性
  • val只能重写另一个val 或 重写不带参数的方法(函数)
class AObject {

  val name :String = "A"

  def sal(): String = {
    "AObject sal method"
  }

}

class BObject extends AObject {

  override val name :String = "B"

  override val sal :String= "1000"

}

其底层对应生成了一个公共的getter方法

  public String sal()
  {
    return this.sal;
  }
  
  private final String sal = "1000";
  • 匿名对象的创建方式和Java基本一样.
new 抽象类/接口 {
    // 实现对应的方法和属性
}

③-X Scala中的抽象类

③-① Why

抽象类的出现主要是有些类并不需要立马实现相应的方法或者初始化变量.而只是定义好一个类的骨架,即描述
好要做的事情,具体的实现延迟到子类中

③-② How

语法和规则

抽象类的语法,必须用abstact修饰class.

  • 类中没有方法体的方法,没有初始化的字段都为抽象
  • 只要类中有抽象成员,那么这个类必须用abstact修饰为抽象类,旦抽象类不一定要包含抽象成员(当然不包含还设计成抽象类就是傻子)
abstract class Person() {
    var name :String
    def printName
}

③-③ Details

  • 子类继承抽象类,要么全部实现抽象成员.要么也声明为抽象类.
  • 子类对抽象类的方法是实现,不是重写,无需加override标记.
  • 抽象方法不能用final和private修饰,这样子类无法实现.永远为抽象,永远没法用.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335