继承的概念和基本原理

44 阅读1分钟

多个类之间的关系

package level02

object Class11 {
  class Boss {
    def power():Unit = {
      println("Boss 有权力....")
    }
    var car = "豪车"
  }
  class NoBody extends Boss{

  }
  def main(args:Array[String]):Unit = {
    val b = new NoBody()
    println(b.car)
    b.power()
  }
}

子类对父亲的同名方法进行重写

package level02

object Class11 {
  class Boss {
    def test():Unit={}
    def power():Unit = {
      println("Boss 有权力....")
    }
    var car = "豪车"
  }
  class NoBody extends Boss{
    def run():Unit = {
      
    }
    override def power():Unit = {
      println("老莫,我想吃鱼了")
    }
  }
  def main(args:Array[String]):Unit = {
    val b = new NoBody()
    println(b.car)
    b.power()
    b.run()
  }
}

带参构造器

package level02

object Class12 {
  class Dog(var name:String,var age:Int) {
    println(s"Dog${name},${age}构造器被调用")
  }
  class RuralDog(name:String,age:Int)extends Dog(name, age) {
    println("RuralDog的构造器...")
  }
  
  def main(arg: Array[String]): Unit = {
    new RuralDog("旺财",3)
  }
}

相比父类,子类有新的属性

package level02

object Class13 {
  class Dog(var name:String,var age:Int) {
    println(s"Dog${name},${age}构造器被调用")
  }
  class RuralDog(name:String,age:Int,var color:String) extends Dog(name, age) {
    println(s"RuralDog的构造器...${color}")
  }

  def main(arg: Array[String]): Unit = {
    new RuralDog("旺财",3,"土黄色")
  }
}

题目:你正在设计一个二维游戏的界面,需要用很多的点来表示游戏中的角色。 设计一个Point类,其x和y可以通过构造器提供。 它有几个方法:

  1. 方法1: 计算自己在哪个象限。 whereAmI():String
  2. 2.方法2: 计算和坐标原点的距离。getDist():Double
  3. 3.方法3: 计算与另一个点的距离。fromPoint(other:Point):Double
  4. 4.方法4: 重写equals 判断是否是同一个点(x和y都相等就是同一个点)。
  5. 5.方法5: 重写toString,更友好的输出点的信息。 再设计一个子类LabelPoint它来继承Point类,其构造器接收一个标签值和x,y坐标。 例如: New LabelPoint("black",1,2)
// 二维游戏点坐标类(基础父类)
class Point(val x: Double, val y: Double) {
  // 方法1:判断当前点所在象限(游戏中可用于区域划分、阵营判定等)
  def whereAmI(): String = {
    (x, y) match {
      case (0.0, 0.0) => "原点(无象限)"
      case (x, y) if x > 0 && y > 0 => "第一象限"
      case (x, y) if x < 0 && y > 0 => "第二象限"
      case (x, y) if x < 0 && y < 0 => "第三象限"
      case (x, y) if x > 0 && y < 0 => "第四象限"
      case (0.0, _) => "x轴上(无象限)"
      case (_, 0.0) => "y轴上(无象限)"
    }
  }

  // 方法2:计算到坐标原点的距离(游戏中可用于判定角色是否在技能范围、安全区等)
  def getDist(): Double = {
    math.sqrt(x * x + y * y)
  }

  // 方法3:计算与另一个点的距离(游戏中可用于角色间距判定、攻击范围检测等)
  def fromPoint(other: Point): Double = {
    val dx = x - other.x // 横向距离差
    val dy = y - other.y // 纵向距离差
    math.sqrt(dx * dx + dy * dy) // 欧氏距离公式
  }

  // 方法4:重写equals,坐标完全相同则判定为同一点(游戏中可用于判定是否重叠、碰撞等)
  override def equals(obj: Any): Boolean = {
    obj match {
      case other: Point => x == other.x && y == other.y // 仅比较坐标(忽略其他可能的扩展属性)
      case _ => false // 非Point类型直接返回不相等
    }
  }

  // 方法5:重写toString,友好输出点信息(游戏调试时便于查看坐标)
  override def toString(): String = {
    s"Point(坐标: ($x, $y), 象限: ${whereAmI()}, 到原点距离: ${getDist().formatted("%.2f")})"
  }

  // 可选:重写hashCode(与equals配套,避免集合中判重异常)
  override def hashCode(): Int = {
    val prime = 31
    var result = 1
    result = prime * result + x.hashCode()
    result = prime * result + y.hashCode()
    result
  }
}

// 带标签的游戏点类(子类,用于区分不同角色/物体,如"玩家"、"敌人"、"道具"等)
class LabelPoint(val label: String, x: Double, y: Double) extends Point(x, y) {
  // 重写toString,增加标签信息(游戏中便于区分不同类型的点)
  override def toString(): String = {
    s"LabelPoint(标签: $label, 坐标: ($x, $y), 象限: ${whereAmI()}, 到原点距离: ${getDist().formatted("%.2f")})"
  }

  // 可选:扩展方法 - 判定当前点是否与同标签的点重叠(游戏中可用于同类型角色碰撞检测)
  def isSameLabelOverlap(other: LabelPoint): Boolean = {
    this.label == other.label && this.equals(other)
  }
}

// 游戏场景测试代码(验证功能可用性)
object GamePointTest {
  def main(args: Array[String]): Unit = {
    // 1. 测试基础Point类
    val playerPos = new Point(3.0, 4.0) // 玩家坐标
    val enemyPos = new Point(-2.0, 5.0) // 敌人坐标
    val origin = new Point(0.0, 0.0) // 原点(比如出生点)

    println("=== 基础Point类测试 ===")
    println(playerPos) // 测试toString
    println(s"玩家与敌人的距离:${playerPos.fromPoint(enemyPos).formatted("%.2f")}") // 测试两点距离
    println(s"敌人是否在原点:${enemyPos.equals(origin)}") // 测试equals
    println(s"原点信息:$origin") // 测试原点的象限判定

    // 2. 测试LabelPoint子类
    val player = new LabelPoint("玩家A", 3.0, 4.0)
    val enemy = new LabelPoint("敌人B", -2.0, 5.0)
    val item = new LabelPoint("金币", 3.0, 4.0) // 与玩家同坐标的道具

    println("\n=== LabelPoint子类测试 ===")
    println(player) // 测试子类toString
    println(enemy)
    println(item)
    println(s"玩家与金币是否同标签重叠:${player.isSameLabelOverlap(item)}") // 测试扩展方法
    println(s"玩家与金币坐标是否相同:${player.equals(item)}") // 继承父类equals方法
    println(s"敌人到玩家的距离:${enemy.fromPoint(player).formatted("%.2f")}") // 继承父类距离方法
  }
}