题目
(一)案例背景
你正在设计一个二维游戏的界面,需要用很多的点来表示游戏中的角色。
设计一个 Point 类,其 x 和 y 可以通过构造器提供。
它有几个方法:
- 方法 1:计算自己在哪个象限。 whereAmI():String
- 方法 2:计算和坐标原点的距离。 getDist():Double
- 方法 3:计算与另一个点的距离。 fromPoint(other:Point):Double
- 方法 4:重写 equals 判断是否是同一个点 (x 和 y 都相等就是同一个点)。
- 方法 5:重写 toString,更友好的输出点的信息。
再设计一个子类 LabelPoint 它来继承 Point 类,其构造器接收一个标签值和 x, y 坐标。
例如: New LabelPoint("black",1,2)
(二)任务分析
我们需要创建一个新的文件来实现这个功能,类名和方法名我们这里都有了,那么就按照要求逐步来实现即可。
父类名:Point;
属性名:x,y
方法:whereAmI, getDist,fromPoint, equals, toString。
子类名:LabelPoint
属性:label。
代码实现
package FinalsProject.teacher
/*
* 属性
* 方法
*
* */
object class01 {
class Point(var x: Double, var y: Double) {
def whereAmI():String = {
if (x > 0 && y > 0) "第一象限"
else "未知"
}
def getDist(): Double = {
Math.sqrt(x * x + y * y)
}
def fromPoint(other:Point): Double = {
val dx = x - other.x
val dy = y - other.y
Math.sqrt(dx*dx + dy*dy)
}
override def toString: String = {
s"Point(${x}, ${y})"
}
override def equals(obj: Any): Boolean = {
val other = obj.asInstanceOf[Point]
other.x == x && other.y == y
}
}
class LabelPoint(val label:String, x:Double, y:Double) extends Point(x, y){
override def toString: String = {
s"LabelPoint(${label},${x},${y})"
}
}
def main(args: Array[String]): Unit = {
val p1 = new Point(1, 1)
val p3 = new Point(1, 1)
val p2 = new Point(1, 2)
println(p1.whereAmI())
println(p1.getDist())
println(p1.fromPoint(p2))
println(p1 == p3)
var p4 = new LabelPoint("black", 1, 2)
println( p4.fromPoint(p2))
println( p4)
}
}
代码解析
Point 类解析
类定义与属性
class Point(var x: Double, var y: Double)
- 定义 Point 类,包含两个可变属性 x 和 y
- 使用
var关键字表示这些属性是可变的 - 通过构造器参数直接初始化属性
象限判断方法
def whereAmI():String = {
if (x > 0 && y > 0) "第一象限"
else "未知"
}
- 根据 x 和 y 坐标的正负判断所在象限
- 当前实现只判断了第一象限,其他情况返回"未知"
距离计算方法
def getDist(): Double = {
Math.sqrt(x * x + y * y)
}
- 使用勾股定理计算点到原点的距离
- 公式:√(x² + y²)
两点间距离计算
def fromPoint(other:Point): Double = {
val dx = x - other.x
val dy = y - other.y
Math.sqrt(dx*dx + dy*dy)
}
- 计算当前点与另一个点之间的距离
- 使用两点间距离公式:√((x₁-x₂)² + (y₁-y₂)²)
toString 方法重写
override def toString: String = {
s"Point(${x}, ${y})"
}
- 重写 toString 方法,提供友好的字符串表示
- 使用字符串插值格式化输出
equals 方法重写
override def equals(obj: Any): Boolean = {
val other = obj.asInstanceOf[Point]
other.x == x && other.y == y
}
- 重写 equals 方法判断两个点是否相等
- 使用类型转换将 obj 转换为 Point 类型
- 比较两个点的 x 和 y 坐标是否完全相同
LabelPoint 子类解析
类定义与继承
class LabelPoint(val label:String, x:Double, y:Double) extends Point(x, y)
- LabelPoint 继承自 Point 类
- 新增 label 属性用于标记点的类型
- 继承父类的 x 和 y 坐标属性
toString 方法重写
override def toString: String = {
s"LabelPoint(${label},${x},${y})"
}
- 重写 toString 方法,在输出中包含标签信息
- 格式化为 LabelPoint(标签,x坐标,y坐标)
测试代码解析
对象创建与测试
val p1 = new Point(1, 1)
val p3 = new Point(1, 1)
val p2 = new Point(1, 2)
- 创建多个 Point 实例用于测试
方法调用测试
println(p1.whereAmI()) // 测试象限判断
println(p1.getDist()) // 测试到原点距离
println(p1.fromPoint(p2)) // 测试两点间距离
println(p1 == p3) // 测试相等性判断
子类测试
var p4 = new LabelPoint("black", 1, 2)
println(p4.fromPoint(p2)) // 子类调用父类方法
println(p4) // 测试子类 toString
总结
这个实现展示了 Scala 面向对象编程的核心概念:
- 类的定义和构造器使用
- 方法的定义和实现
- 继承关系的建立
- 方法重写(override)
- 类型转换在 equals 方法中的应用
- 字符串插值的使用