美文网首页
【2019-05-23】组合和继承

【2019-05-23】组合和继承

作者: BigBigFlower | 来源:发表于2019-05-23 10:08 被阅读0次

类之间的两种基本关系:组合和继承
组合指一个类持有另一个的引用,借助被引用的类完成任务。继承是超类/子类的关系。

package org.stairwaybook.layout
object Element {
  private class ArrayElement(
    val contents: Array[String]
  ) extends Element

  private class LineElement(s: String) extends Element {
    val contents = Array(s)
    override def width = s.length
    override def height = 1
  }

  private class UniformElement(
    ch: Char,
    override val width: Int,
    override val height: Int
  ) extends Element {
    private val line = ch.toString * width
    def contents = Array.make(height, line)
  }
//创建带有字符串的元素
  def elem(contents:  Array[String]): Element =
    new ArrayElement(contents)

  def elem(chr: Char, width: Int, height: Int): Element =
    new UniformElement(chr, width, height)

  def elem(line: String): Element =
    new LineElement(line)
}


import Element.elem
//定义抽象类和方法
abstract class Element {
  def contents:  Array[String]
//定义无参数方法
  def width: Int = contents(0).length
  def height: Int = contents.length

  def above(that: Element): Element = {
    val this1 = this widen that.width
    val that1 = that widen this.width
    elem(this1.contents ++ that1.contents)
  }

  def beside(that: Element): Element = {
    val this1 = this heighten that.height
    val that1 = that heighten this.height
    elem(
      for ((line1, line2) <- this1.contents zip that1.contents) 
      yield line1 + line2)
  }

  def widen(w: Int): Element = 
    if (w <= width) this
    else {
      val left = elem(' ', (w - width) / 2, height) 
      var right = elem(' ', w - width - left.width, height)
      left beside this beside right
    }

  def heighten(h: Int): Element = 
    if (h <= height) this
    else {
      val top = elem(' ', width, (h - height) / 2)
      var bot = elem(' ', width, h - height - top.height)
      top above this above bot
    }

  override def toString = contents mkString "\n"
}

object LayoutElement {
  def main(args: Array[String]) {
    
    println("example [\n" + example + "\n]")
  }

  def example = {
    val column1 = elem("hello") above elem("***")
    val column2 = elem("***") above elem("world")
    column1 beside column2
  }
}

扩展类

object Ex2 {
  abstract class Element {
    def contents: Array[String]
    val height = contents.length
    val width = 
      if (height == 0) 0 else contents(0).length
  }
//Element抽象类不能new Element,可以创建扩展类并实现抽象的contents方法的子类。
  class ArrayElement(conts: Array[String]) extends Element {
    def contents: Array[String] = conts
  }

  def main(args: Array[String]) {
    val arrayElem = new ArrayElement(Array("foo"))
    println("arrayElem [" + arrayElem + "]")

    val a123 =
      Array(1, 2, 3).toString
    val abcLen =
      "abc".length
    val helloLen =
      "hello".length  // no () because no side-effect
      println()       // better to not drop the ()
      val e: Element = new ArrayElement(Array("hello"))

    println("a123 [" + a123 + "]")
    println("abcLen [" + abcLen + "]")
    println("helloLen [" + helloLen + "]")
    println("e [" + e + "]")
  }
}

继承表示超类的所有成员也是子类的成员。两个例外:(1)超类的私有成员不会被子类继承(2)超类中的成员若与子类中实现的成员具有相同名称和参数则不会被子类继承。

重写方法和字段

object Ex3 {
  abstract class Element {
    def contents: Array[String]
    def height: Int = contents.length
    def width: Int = if (height == 0) 0 else contents(0).length
  }
//改变ArrayElement类中contents的实现将其从一个方法变为一个字段,无需修改Element中的contents长度抽象方法定义
  class ArrayElement(conts: Array[String]) extends Element {
    val contents: Array[String] = conts
  }

  def main(args: Array[String]) {
    val arrayElem = new ArrayElement(Array("foo"))
    println("arrayElem [" + arrayElem + "]")
  }
}

object Ex9  {
  abstract class Element {
    def contents: Array[String]
    def height: Int = contents.length
    def width: Int = if (height == 0) 0 else contents(0).length
  }
//定义参数化对象contents
  class ArrayElement(
    val contents: Array[String]
  ) extends Element
//调用超类构造器,扩展ArrayElement的LineElement类
  class LineElement(s: String) extends ArrayElement(Array(s)) {
    override def width = s.length
    override def height = 1
  }
//多态和动态绑定
//动态绑定是指在执行期间(非编译期)判断所引用对象的实际类型,根据其实际的类型调用其相应的方法。程序运行过程中,把函数(或过程)调用与响应调用所需要的代码相结合的过程称为动态绑定。
//多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。
//定义拥有给给定长度和高度并充满指定字符的新的element形式
  class UniformElement(
    ch: Char, 
//使用override修饰符,子类成员重写父类的具体成员
    override val width: Int,
    override val height: Int 
  ) extends Element {
    private val line = ch.toString * width
    def contents = Array.make(height, line)
  }

  def main(args: Array[String]) {
    val e1: Element = new ArrayElement(Array("hello", "world"))
    val ae: ArrayElement = new LineElement("hello")
    val e2: Element = ae
    val e3: Element = new UniformElement('x', 2, 3)

    println("e1 [" + e1 + "]")
    println("ae [" + ae + "]")
    println("e2 [" + e2 + "]")
    println("e3 [" + e3 + "]")
  }
}

定义final成员,确保一个成员不被子类重写

//声明final方法
class ArrayElement extends Element {
    final override def demo() {
      println("ArrayElement's implementation invoked")
    }
  }

使用组合和继承

object Ex11  {
  abstract class Element {
  
    def contents: Array[String]
  
    def width: Int =
      if (height == 0) 0 else contents(0).length
  
    def height: Int = contents.length
  
    def above(that: Element): Element =
      new ArrayElement(this.contents ++ that.contents)
  
    def beside(that: Element): Element =
      new ArrayElement(
        for (
          (line1, line2) <- this.contents zip that.contents
        ) yield line1 + line2
      )
  
    override def toString = contents mkString "\n"
  }

  class LineElement(s: String) extends Element {
    val contents = Array(s)
    override def width = s.length
    override def height = 1
  }

  class ArrayElement(conts: Array[String]) extends Element {
    def contents: Array[String] = conts
  }

  def main(args: Array[String]) {
    val lineElem = new LineElement("foo")
    println("lineElem [" + lineElem + "]")

  }
}

实现above、beside、和toString

object Ex10  {
  abstract class Element {
    def contents: Array[String]
    def height: Int = contents.length
    def width: Int = if (height == 0) 0 else contents(0).length

    def above(that: Element): Element =
      new ArrayElement(this.contents ++ that.contents)

    def beside(that: Element): Element = {
      val contents = new Array[String](this.contents.length)
      for (i <- 0 until this.contents.length) 
        contents(i) = this.contents(i) + that.contents(i)
      new ArrayElement(contents)
    }

    def beside2(that: Element): Element = 
      new ArrayElement(
        for (
          (line1, line2) <- this.contents zip that.contents
        ) yield line1 + line2
      )

    override def toString = contents mkString "\n"

  }

  class LineElement(s: String) extends Element {
    val contents = Array(s)
    override def width = s.length
    override def height = 1
  }

  class ArrayElement(conts: Array[String]) extends Element {
    def contents: Array[String] = conts
  }

  def main(args: Array[String]) {
    val lineElem = new LineElement("foo")
    println("lineElem [" + lineElem + "]")

    val zip1 =
      Array(1, 2, 3) zip Array("a", "b")
    val zip2 =
      Array((1, "a"), (2, "b"))
    println("zip1 [" + zip1 + "]")
    println("zip2 [" + zip2 + "]")
  }
}

定义工厂方法,工厂对象包含了构建其他对象的方法。

object Ex12  {
  import Element.elem
  abstract class Element {
    def contents: Array[String]
    def width: Int =
      if (height == 0) 0 else contents(0).length
    def height: Int = contents.length
    def above(that: Element): Element =
      elem(this.contents ++ that.contents)
  
    def beside(that: Element): Element =
      elem(
        for (
          (line1, line2) <- this.contents zip that.contents
        ) yield line1 + line2
      )
  
    override def toString = contents mkString "\n"
  }

//带有工厂方法的工厂对象
//Element伴生对象包含三个重载elem方法变体,每一个变体构建一个不同的布局对象。
  object Element {
    def elem(contents: Array[String]): Element = 
      new ArrayElement(contents)
  
    def elem(chr: Char, width: Int, height: Int): Element = 
      new UniformElement(chr, width, height)
  
    def elem(line: String): Element = 
      new LineElement(line)
  }

  class ArrayElement(conts: Array[String]) extends Element {
    def contents: Array[String] = conts
  }

  class LineElement(s: String) extends ArrayElement(Array(s)) {
    override def width = s.length
    override def height = 1
  }

  class UniformElement(
    ch: Char, 
    override val width: Int,
    override val height: Int 
  ) extends Element {
    private val line = ch.toString * width
    def contents = Array.make(height, line)
  }

  def main(args: Array[String]) {
    val lineElem = new LineElement("foo")
    println("lineElem [" + lineElem + "]")
  }
}

相关文章

  • 【2019-05-23】组合和继承

    类之间的两种基本关系:组合和继承组合指一个类持有另一个的引用,借助被引用的类完成任务。继承是超类/子类的关系。 扩...

  • 组合寄生继承和组合继承

    1.js中实现组合继承(B继承A): function A(name){ this.name = name; ...

  • js一些技巧.md

    js中的constructor和prototype 组合继承与寄生继承 组合继承 可以继承实例属性和方法,也可以继...

  • 组合和继承

    需要一个类的某个功能使用组合需要那个类的所有功能使用继承组合优于继承,接口优于实现

  • PHP学习2

    六.继承与多态 1. 类的组合和继承(继承===“是、像”、“父与子”,组合===“需要”、“整体与局部”) 组合...

  • ES5和ES6 实现继承方式

    在ES5 中:通过原型链实现继承的,常见的继承方式是组合继承和寄生组合继承;在ES6中:通过Class来继承 组合...

  • [收藏文章]《Java编程思想》之重点笔记

    1、组合和继承之间的选择 组合和继承都允许在新的类中放置子对象,组合是显式的这样做,而继承则是隐式的做。 组合技术...

  • 【python面试指北】3.类和面向对象

    面向对象编程 封装、继承、多态 组合与继承 优先使用组合(has a)而非继承(is a) 类变量和实例变量的区别...

  • 继承、组合、聚合

    继承和组合的区别 继承是 is A,组合是has A。 车有轮子、引擎、轴承。 车不能继承轮子、引擎、轴承,因为车...

  • 组合模式(Composite)

    在探讨Java组合模式之前,先要明白几个概念的区别:继承、组合和聚合。 继承是is-a的关系。组合和聚合有点像,有...

网友评论

      本文标题:【2019-05-23】组合和继承

      本文链接:https://www.haomeiwen.com/subject/ywyyzqtx.html