1 类
- 编写一个
Time
类,加入只读属性hours
和minutes
,和一个检查某一时刻是否早于另一时刻的方法before(other:Time):Boolean
。Time
对象应该以new Time(hrs,min)
方式构建。
class Time(val hrs:Int,val min:Int){
val hours = hrs
val minutes = min
def before(other:Time): Boolean ={
if(other.hours > this.hours){
return true
}
if(other.hours == this.hours){
if(other.minutes > this.minutes){
return false
}
}
return false
}
}
- 创建一个
Student
类,加入可读写的JavaBeans
属性name
(类型为String
)和id
(类型为Long
)。有哪些方法被生产? (用javap
查看。 )你可以在Scala
中调用JavaBeans
的getter
和setter
方法吗?
class Student{
@BeanProperty var id:Long = _
@BeanProperty var name:String = _
}
javap -c 查看反编译代码:
C:\Users\lenovo>javap -c D:\AboutMyWork\IDEA-WorkSpace\ScalaDemo\ScalaExamples\target\classes\com\nefu\practice\Student.class
Compiled from "A_Class_2_Stundent.scala"
public class com.nefu.practice.Student {
public long id();
Code:
0: aload_0
1: getfield #15 // Field id:J
4: lreturn
public void id_$eq(long);
Code:
0: aload_0
1: lload_1
2: putfield #15 // Field id:J
5: return
public void setId(long);
Code:
0: aload_0
1: lload_1
2: putfield #15 // Field id:J
5: return
public java.lang.String name();
Code:
0: aload_0
1: getfield #24 // Field name:Ljava/lang/String;
4: areturn
public void name_$eq(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #24 // Field name:Ljava/lang/String;
5: return
public void setName(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #24 // Field name:Ljava/lang/String;
5: return
public long getId();
Code:
0: aload_0
1: invokevirtual #30 // Method id:()J
4: lreturn
public java.lang.String getName();
Code:
0: aload_0
1: invokevirtual #33 // Method name:()Ljava/lang/String;
4: areturn
public com.nefu.practice.Student();
Code:
0: aload_0
1: invokespecial #37 // Method java/lang/Object."<init>":()V
4: return
}
2 对象
- 编写一个
Conversions
对象,加入inchesToCentimeters
,gallonsToLiters
和milesToKilometers
方法
class Conversions{
def inchesToCentimeters(inches:Double):Double={
/*
1英寸(in)=2.54厘米(cm)
*/
2.54 * inches
}
def gallonsToLiters(gallons:Double):Double={
/*
1美制加仑(us gal)=3.7854118公升(l)
*/
3.7854118 * gallons
}
def milesToKilometers(miles:Double):Double={
/*
1英里(mi)=1.609344千米(km)
*/
miles * 1.609344
}
}
- 定义一个
Point
类和一个伴生对象,使得我们可以不用new
而直接用Point(3,4)
来构造Point
实例 apply 方法的使用
object Point {
def apply(x: Int, y: Int): Point = new Point(x, y)
}
class Point(x:Int = 0,y:Int = 0){
}
- 编写一个
Scala
应用程序,使用App
特质,以反序打印命令行参数,用空格隔开。举例来说,scala Reverse Hello World
应该打印World Hello
object B_Object_3_Reverse extends App {
args.reverse.mkString(" ")
}
- 编写一个扑克牌 4 种花色的枚举,让其
toString
方法分别返回♣,♦,♥,♠,并实现一个函数,检查某张牌的花色是否为红色
object Poker extends Enumeration {
//scala里的类型,除了在定义class,trait,object时会产生类型,
// 还可以通过type关键字来声明类型。
type Poker = Value //type相当于声明一个类型别名 用Poker代替Value类型
val plumBlossom = Value("♣")
val squarePiece = Value("♦")
val hearts = Value("♥")
val spades = Value("♠")
def isRed(poker:Poker): Boolean ={
poker == hearts || poker == squarePiece
}
override def toString(): String = {
Poker.values.mkString(",")
}
}
- 练习使用包的各种声明方式,并查看他们的不同
class Statement{
/*
1.在 Scala 中, import 语句可以出现在任何地方,
并不仅限于文件顶部。
*/
/*
2.在 Java 中如果想要导入包中所有的类,可以通过通配符星号,
Scala 中采用下划线
*/
import java.util._
println(Math.random())
/*
3.如果不想要某个包中全部的类,而是其中的几个类,可以采用选取器(大括号)
*/
import scala.collection.mutable.{HashMap}
var map = new HashMap()
}
- 编写一段程序,将
Java
哈希映射中的所有元素拷贝到Scala
哈希映射。用引入语句重命名这两个类。
import java.util.{HashMap=>JavaHashMap}
import scala.collection.mutable.{HashMap=>ScalaHashMap}
var jhm = new JavaHashMap[String,String]()
var shm = new ScalaHashMap[String,String]()
jhm.put("a","1");
jhm.put("b","2");
jhm.put("c","3");
for(key <- jhm.keySet().toArray()){
shm += (key.asInstanceOf[String] -> jhm.get(key))
}
println(shm.mkString(" "))
3 继承
- 扩展如下的
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 CheckingAccount(initialBalance:Double) extends BankAccount(initialBalance){
private var balance = initialBalance
override def deposit(amount:Double) = { balance += (amount - 1); balance}
override def withdraw(amount:Double)={balance -= (amount + 1); balance}
}
- 扩展前一个练习的
BankAccount
类,新类SavingsAccount
每个月都有利息产生
(earnMonthlyInterest
方法被调用),并且有每月三次免手续费的存款或取款。在earnMonthlyInterest
方法中重置交易计数。
override def deposit(amount:Double) = {
if(this.monthlyCount < 4) {
this.monthlyCount = this.monthlyCount + 1
super.deposit(initialBalance)
}else{
super.deposit(initialBalance - 1)
}
}
override def withdraw(amount:Double) = {
if(this.monthlyCount < 4) {
this.monthlyCount = this.monthlyCount + 1
super.withdraw(initialBalance)
}else{
super.withdraw(initialBalance + 1)
}
}
def earnMonthlyInterest(): Unit ={
this.monthlyCount = 0
}
- 定义一个抽象类
Item
,加入方法price
和description
。SimpleItem
是一个在构造器中给出价格和描述的物件。利用val
可以重写def
这个事实。Bundle
是一个可以包含其他物件的物件。其价格是打包中所有物件的价格之和。同时提供一个将物件添加到打包当中的机制,以及一个适合的description
方法
abstract class Item{
def price():Double
def description():String
override def toString() {
println("price is: " + price() + ", description is: " + description())
}
}
class SimpleItem(val price:Double,val description:String) extends Item{
}
class Bundle extends Item {
val items = new ArrayBuffer[Item]()
def addItem(item: Item): Unit ={
items += item
}
override def price(): Double = {
var sumPrice:Double = 0d
this.items.foreach(sumPrice += _.price())
sumPrice
}
override def description(): String = {
items.mkString(" ")
}
}
- 设计一个
Point
类,其 x和 y坐标可以通过构造器提供。提供一个子类LabeledPoint
,其构造 器 接 受 一 个 标 签 值 和x
,y
坐 标 , 比 如 :new
LabeledPoint( “BlackThursday” ,1929,230.07)
class Point(x:Double,y:Double){
}
class LabeledPoint(Label:String,x:Double,y:Double) extends Point{
}
- 定义一个抽象类 Shape,一个抽象方法 centerPoint,以及该抽象类的子类 Rectangle和 Circle。为子类提供合适的构造器,并重写 centerPoint 方法
abstract class Shape{
def centerPoint()
}
class Rectangle(long: Double,width:Double) extends Shape {
override def centerPoint(): Unit = ???
}
class Circle(radius:Double) extends Shape {
override def centerPoint(): Unit = ???
}
- 提供一个
Square
类,扩展自java.awt.Rectangle
并且是三个构造器:一个以给定的端点和宽度构造正方形,一个以(0,0)为端点和给定的宽度构造正方形,一个以(0,0)为端点,0 为宽度构造正方形
class Square(point:Point,width:Int) extends java.awt.Rectangle(point.x,point.y,width,width){
def this(){
this(new Point(0,0),0)
}
def this(width:Int){
this(new Point(0,0),width)
}
}
5 特质
object E_Trait_RenctangleLike {
def main(args: Array[String]): Unit = {
val egg = new Ellipse2D.Double(5,10,20,30) with RenctangleLike
println("x = " + egg.getX + " y = " + egg.getY)
egg.translate(10,-10)
println("x = " + egg.getX + " y = " + egg.getY)
egg.grow(10,20)
println("x = " + egg.getX + " y = " + egg.getY)
}
}
trait RenctangleLike{
this:Ellipse2D.Double=>
def translate(x:Double,y:Double){
this.x = x
this.y = y
}
def grow(x:Double,y:Double){
this.x += x
this.y += y
}
}
x = 5.0 y = 10.0
x = 10.0 y = -10.0
x = 20.0 y = 10.0
6 类型参数
- 定义一个不可变类
Pair[T,S]
, 带一个swap
方法,返回组件交换过位置的新对偶
class Pair[T,S](val t:T,val s:S){
def swap() = new Pair(s,t)
}
- 定义一个可变类
Pair[T]
,带一个swap
方法,交换对偶中组件的位置。
class Pairs[T](val t:T,val s:T){
def swap() = new Pairs(s,t)
}
- 给定类
Pair[T, S]
,编写一个泛型方法swap
,接受对偶作为参数并返回组件交换过位置的新对偶。
class Pairss[T,S](val t:T,val s:S){
def swap(t:T,s:T) = new Pairss(s,t)
}
- 编写一个泛型方法
middle
,返回任何Iterable[T]
的中间元素。举例来说,middle(“World” )
应得到’ r’
。
def middle[T](iter:Iterable[T]):T={
val array = iter.toArray
array(array.length / 2)
}
- 给定可变类
Pair[S,T]
,使用类型约束定义一个swap
方法,当类型参数相同时可以被调用。
class Pair[S,T](val s:S,val t:S){
def swap(s:S,t:T): Unit ={
if(s.getClass == t.getClass) new Pair(t,s)
}
}