scala组合和继承

2020-05-15  本文已影响0人  平头哥2

组合和继承

1. 定义无参方法

/**
 * 抽象类
 *
 */
abstract class Element {
  /**
   * 该方法只有声明没有实现,是抽象方法,抽象方法的声明不需要添加 abstract 关键字,
   * 只要声明,没有实现就是抽象方法
   * 包含抽象成员的类是抽象类,在类上加 abstract 关键字
   *
   * @return
   */
  def contents : Array[String]

  /**
   * 不带 () 来定义的方法叫做 无参方法
   * @return
   */
  def height : Int = contents.length
  def width: Int = if(height == 0) 0 else contents(0).length

  /**
   * 带 () 的方法: 空圆括号方法
   * 对于() 的方法,调用的时候可以去掉()
   * 对于 无参方法,调用的时候不能新增()
   */
  def demo(): Unit = {}
}

对于没有参数且只通过读取所在对象字段的方式访问可变状态的情况下尽量使用无参方法,这样的做法是支持所谓的<font color=red size=3>统一访问原则</font>


abstract class Element {
  def contents : Array[String]
  //将def 换成 val ,从代码层面来看,完全等价,对于调用方来说,调用的代码无需改变
  // 唯一的区别就是字段访问的速度可能会快一点
  val height : Int = contents.length
  val width: Int = if(height == 0) 0 else contents(0).length
}

2. 扩展类

abstract class Element {

  def contents : Array[String]
  val height : Int = contents.length
  val width: Int = if(height == 0) 0 else contents(0).length
}
//扩展类
class ArrayElement(consts: Array[String]) extends Element {
  //重写方法
  override def contents: Array[String] = consts
}
def main(args: Array[String]): Unit = {
  val ele = new ArrayElement(Array("hello","world"))
  val eles: Element = new ArrayElement(Array("hello","world"))//父类引用指向子类对象
}
class WontCompile {

  private val f = 1;
  def f(): Unit ={ //f is already defined in the scope
  }
}

3. 定义参数化字段

/**
 * 类上声明了 val contents: Array[String]
 * 表明了:类同时定义参数和同名字段的简写方式
 * 具体来说: 类 ArrayElement 具备了一个 不能被重新赋值的contents字段
 * 该字段可以被外界访问,该字段被初始化为参数的值
 * 可以给这些参数加上修饰符 private,protected ,override
 * @param contents
 */
class ArrayElement(val contents: Array[String]) extends Element {}

等价于下面的定义方式

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

案例:

class Cat {val dangerous = false}

class Tiger(override val dangerous: Boolean, private var age: Int) extends Cat

4. 调用超类的构造方法

class ArrayElement(val contents: Array[String]) extends Element {
  println("hello world")
}
class LineElement(s: String) extends ArrayElement(Array(s)) {
  override def height: Int = 1
  override def width: Int = s.length
}

def main(args: Array[String]): Unit = {
  val ele: ArrayElement = new LineElement("hello")
  println(ele.width)
}
//--------------输出结果---------------------
hello world
5

5. 多态和动态绑定

同Java

6. 声明final成员

同Java

7. 案例

/**
 * 定义工厂方法
 */
object Element {

  def ele(contents: Array[String]) = new ArrayElement(contents)

  def ele(line: String) = new LineElement(line)

  def ele(ch: Char, width: Int, height: Int) = new UniformElement(ch, width, height)

}


/**
 * 抽象类
 *
 */
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)

  //使用工厂方法重构 above
  def above3(that: Element): Element = Element.ele(this.contents ++ that.contents)

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

  // 使用zip函数重构 beside
  def beside2(that: Element): Element = {
    new ArrayElement(
      for ((line1, line2) <- (this.contents zip that.contents)) yield line1 + line2
    )
  }

  // 使用工厂方法重构 beside2
  def beside3(that: Element): Element = {
    Element.ele(
      for ((line1, line2) <- this.contents zip that.contents) yield line1 + line2
    )
  }

  // toString 是个无参方法,并没有带上(), 这符合统一访问原则
  override def toString: String = contents mkString "\n"
}

class ArrayElement(val contents: Array[String]) extends Element {}

class LineElement(s: String) extends Element {
  override def contents: Array[String] = Array(s)
}

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

将类私有化

/**
 * 定义工厂方法
 */
object Element {

  def ele(contents: Array[String]) = new ArrayElement(contents)

  def ele(line: String) = new LineElement(line)

  def ele(ch: Char, width: Int, height: Int) = new UniformElement(ch, width, height)

  private class ArrayElement(val contents: Array[String]) extends Element {}

  private class LineElement(s: String) extends Element {
    override def contents: Array[String] = Array(s)
  }

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

    def contents: Array[String] = Array.fill(height)(line)
  }
}


/**
 * 抽象类
 *
 */
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 = Element.ele(this.contents ++ that.contents)

  // 使用工厂方法重构 beside2
  def beside(that: Element): Element = {
    Element.ele(
      for ((line1, line2) <- this.contents zip that.contents) yield line1 + line2
    )
  }

  // toString 是个无参方法,并没有带上(), 这符合统一访问原则
  override def toString: String = contents mkString "\n"
}
上一篇下一篇

猜你喜欢

热点阅读