Open justtreee opened 6 years ago
要点包括:
class Person(name: String, age: Int){}
class Student(name: String, age: Int, var studentNo: String) extends Person(name,age){}
object Test {
def main(args: Array[String]) : Unit = {
val stu = new Student("XXX",18,"2015")
}
}
class Person(name: String, age: Int){
println("Person")
}
class Student(name: String, age: Int, var studentNo: String) extends Person(name,age){
println("Student")
}
object Test {
def main(args: Array[String]) : Unit = {
val stu = new Student("XXX",18,"2015")
}
}
//Person
//Student
可见构造Student类之前,首先会调用Person的主构造方法。
有时候子类从父类继承过来的方法不能满足需要,就需要方法重写。方法重写是实现多态和动态绑定的关键。利用override
关键词实现。
class Person(name: String, age: Int){
def f() = println("Person")
}
class Student(name: String, age: Int, var studentNo: String) extends Person(name,age){
override def f() = println("Student")
}
object Test {
def main(args: Array[String]) : Unit = {
val stu = new Student("XXX",18,"2015")
stu.f()
}
}
//Student
如果父类是抽象类(也就是说方法没有实现),那么子类的方法重写可以不加关键字。
abstract class Person(name: String, age: Int){
def f(): Unit
}
class Student(name: String, age: Int, var studentNo: String) extends Person(name,age){
def f() = println("Student")
}
object Test {
def main(args: Array[String]) : Unit = {
val stu = new Student("XXX",18,"2015")
stu.f()
}
}
//Student
多态”(Polymorphic)也叫“动态绑定”(Dynamic Binding)、“迟绑定”(Late Binding),指“在执行期间(而非编译期间)判断所引用对象的实际类型,根据其实际类型调用其相应的方法。”即指子类的引用可以赋给父类,程序在运行时根据实际类型调用对应的方法 。
abstract class Person(var name: String, var age: Int){
def f(): Unit
def f2(p:Person):Unit
}
class Student(name: String, age: Int) extends Person(name,age){
private var studentNo:Int = 0
def f() = println("Student f()")
def f2(p:Person) = {
println("Student f2()")
println(this.name+" -> "+p.name)
}
}
class Teacher(name: String, age: Int) extends Person(name,age){
private var teacherNo:Int = 0
def f() = println("Teacher f()")
def f2(p:Person) = {
println("Teacher f2()")
println(this.name+" -> "+p.name)
}
}
object Test {
def main(args: Array[String]) : Unit = {
val p1:Person = new Teacher("Tea", 40)
val p2:Person = new Student("Stu", 16)
p1.f2(p2)
p2.f2(p1)
}
}
//Teacher f2()
//Tea -> Stu
//Student f2()
//Stu -> Tea
继承可以重用父类的代码,从而简化程序设计,继承是is-a的关系,apple is a kind of fruit(苹果是一种水果)。还有一种代码重用的方式是组合,组合是has-a的关系(one person has a head)。继承在前面已经讲了,这边只给出组合的使用代码:
class Head
class Body
class Hand
//....
//Person类
abstract class Person(var name:String,var age:Int){
//各类的实例作为该类对象的一部分,通过各类的实例方法实现代码重用
val head:Head=null
val body:Body=null
val hadn:Hand=nulll
//....
}
扩展如下的BankAccount类,新类CheckingAccount 对每次存款和取款都收取1美元的手续费。
class BankAccount(initialBalance : Double) {
private var balance = initialBalance
def deposit (amount : Double) = {
balance += amount
balance
}
def withdraw(amount : Double) = {
balance -= amount
balance
}
}
答:
class BankAccount(initialBalance : Double) {
private var balance = initialBalance
def deposit (amount : Double) = {
balance += amount
balance
}
def withdraw(amount : Double) = {
balance -= amount
balance
}
}
class CheckingAccount(initialBalance: Double) extends BankAccount(initialBalance){ private var balance = initialBalance
override def deposit(amount: Double): Double = { balance = super.deposit(amount)-1 balance }
override def withdraw(amount: Double): Double = { balance = super.withdraw(amount)-1 balance }
}
object Test extends App{ val a = new CheckingAccount(100) println(a.deposit(100)) println(a.withdraw(50)) }
//199.0 //149.0
2. 扩展前一个练习中的BankAccount 类, 新类SavingAccount 每个月都有利息产生 (earnMonthlyInterest方法被调用),并且有每月三次免手续费的存款和取款。在earnMonthlyInterest 方法中重置交易计数
```scala
class BankAccount(initialBalance : Double) {
private var balance = initialBalance
def deposit (amount : Double) = {
balance += amount
balance
}
def withdraw(amount : Double) = {
balance -= amount
balance
}
}
class SavingAccount(initialBalance: Double) extends BankAccount(initialBalance)
{
private var balance = initialBalance
private var cnt = 0
private var interests = balance * 0.018
override def deposit(amount: Double): Double = {
balance += amount
if(cnt > 3){
balance -= 1
}
cnt += 1
balance
}
override def withdraw(amount: Double): Double = {
balance -= amount
if(cnt >= 3){
balance -= 1
}
cnt += 1
balance
}
def earnMonthlyInterest():Double = {
cnt = 0
balance += interests
balance
}
def show() = {
println(balance)
}
}
object Test extends App{
val a = new SavingAccount(100)
println(a.deposit(100))
println(a.withdraw(50))
a.show()
println(a.deposit(100))
a.show()
println(a.withdraw(50))
a.show()
a.earnMonthlyInterest()
a.show()
println(a.deposit(100))
a.show()
}
abstract class Item{
def price: Double
def description: String
}
class SimpleItem(private val iPrice:Double, private val iDescription: String) extends Item{ override def description: String = iDescription
override def price: Double = iPrice }
class Bundle extends Item{ private val items : scala.collection.mutable.ArrayBuffer[SimpleItem] = new scala.collection.mutable.ArrayBuffer[SimpleItem]() def packItems(item: SimpleItem){ items += item } def price() = { var sum:Double = 0 for(i <- items){ sum += i.price } sum }
def description() = { var desc = new scala.collection.mutable.ArrayBuffer[String](); for (i <- items) { desc += i.description }
desc.mkString(",")
} }
object Test extends App{ val b = new Bundle() b.packItems(new SimpleItem(20, "item001")) b.packItems(new SimpleItem(30, "item002")) b.packItems(new SimpleItem(40, "item003"))
println(b.price()) println(b.description()) }
//90.0 //item001,item002,item003
5. 设计一个Point 类, 其 x 和 y 坐标可以通过构造器提供,提供一个子类 LabeledPoint , 其构造器接收一个标签值和 x, y 坐标, 比如: new LabeledPoint(“Black Thursday”, 1929, 230.07)
```scala
abstract class Point(val x:Double, val y:Double){
}
class LabeledPoint(var Label:String, x:Double, y:Double) extends Point(x,y){
}
object Test extends App{
val p = new LabeledPoint("XXX",1,1)
println(p.Label+", "+p.x+", "+p.y)
}
//XXX, 1.0, 1.0
第七章 包和引入
1. 包
下面的代码定义了一个cn.scala.xtwy包 在程序的任何地方都可以通过cn.scala.xtwy.Teacher来使用Teacher这个类
2. 包的作用域
包可以和其他作用域嵌套,可以访问上层作用域的名称。
但在Scala中包名是相对的(Java中是绝对的),也就是说:比如创建
com.horstmann.collection
包,那么编译器在寻找collection.mutable
时就不能找到,因为本意是向使用顶级的scala包的collection
包,而不是随便什么存在与可访问作用域中的子包。而这个解决方法之一就是使用包名,以
_root_
开始:3. 包对象
4. 包可见性
5.
import
高级特性重命名与隐藏方法
隐式引入 每个Scala程序都隐式的引入了以下代码:
练习
import scala._ // 如果去掉用输出 "top level com" , 否则输出 "not top level com" object Test { def main(args : Array[String]) { com.horstmann.impatient.Funcy.foo } }