类之间的两种基本关系:组合和继承
组合指一个类持有另一个的引用,借助被引用的类完成任务。继承是超类/子类的关系。
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 + "]")
}
}
网友评论