Scala实验任务二

任务要求:

对于一个图形绘制程序,用下面的层次对各种实体进行抽象。定义一个 Drawable 的特 质,其包括一个 draw 方法,默认实现为输出对象的字符串表示。定义一个 Point 类表示点, 其混入了 Drawable 特质,并包含一个 shift 方法,用于移动点。所有图形实体的抽象类为Shape,其构造函数包括一个 Point 类型,表示图形的具体位置(具体意义对不同的具体图 形不一样)。Shape 类有一个具体方法 moveTo 和一个抽象方法 zoom,其中 moveTo 将图形从 当前位置移动到新的位置, 各种具体图形的 moveTo 可能会有不一样的地方。zoom 方法实 现对图形的放缩,接受一个浮点型的放缩倍数参数,不同具体图形放缩实现不一样。继承 Shape 类的具体图形类型包括直线类 Line 和圆类 Circle。Line 类的第一个参数表示其位置, 第二个参数表示另一个端点,Line 放缩的时候,其中点位置不变,长度按倍数放缩(注意, 缩放时,其两个端点信息也改变了),另外,Line 的 move 行为影响了另一个端点,需要对 move 方法进行重载。Circle 类第一个参数表示其圆心,也是其位置,另一个参数表示其半 径,Circle 缩放的时候,位置参数不变,半径按倍数缩放。另外直线类 Line 和圆类 Circle 都混入了 Drawable 特质,要求对 draw 进行重载实现,其中类 Line 的 draw 输出的信息样式 为“Line:第一个端点的坐标--第二个端点的坐标)”,类 Circle 的 draw 输出的信息样式为 “Circle center:圆心坐标,R=半径”。如下的代码已经给出了 Drawable 和 Point 的定义, 同时也给出了程序入口 main 函数的实现,请完成 Shape 类、Line 类和 Circle 类的定义。

case class Point(var x:Double,var y:Double) extends Drawable{ def shift(deltaX:Double,deltaY:Double){x+=deltaX;y+=deltaY}

}

trait Drawable{

def draw(){println(this.toString)}

}

// 请完成 Shape 类、Line 类和 Circle 类的定义。

object MyDraw{

def main(args: Array[String]) { val p=new Point(10,30)

p.draw;

val line1 = new Line(Point(0,0),Point(20,20)) line1.draw

line1.moveTo(Point(5,5)) //移动到一个新的点

line1.draw line1.zoom(2) //放大两倍 line1.draw

val cir= new Circle(Point(10,10),5) cir.draw

cir.moveTo(Point(30,20)) cir.draw

cir.zoom(0.5) cir.draw

}

Shape:

因为shape中有抽象类所以需要引用abstract

Line类:

当一个类extends另外一个类的时候,override的规则基本如下:

  • 子类中的方法要覆盖父类中的方法,必须写override(参见foo)
  • 子类中的属性val要覆盖父类中的属性,必须写override(参见nameVal)
  • 父类中的变量不可以覆盖(参见nameVar)

Scala中的override

override是覆盖的意思,在很多语言中都有,在scala中,override是非常常见的,在类继承方面,它和java不一样,不是可写可不写的了,而是必须写的。如果不写而覆盖了对应的属性或者方法的话,编译器就会报错了。今天把scala中的override的各种地方都整理了一遍,以方便以后翻阅。

基础用法

/*
基本的override特性
*/
class A {
  val nameVal = "A"
  var nameVar = "A"

  def foo: String = {
    "A.foo"
  }
}

class B extends A {
  override val nameVal = "B"
  //override var nameVar = "B"  "variable nameVar cannot override a mutable variable"
  override def foo: String = {
    "B.foo"
  }
}

val b1 = new B
b1.foo
b1.nameVal
b1.nameVar

val b2 : A = new B
b2.foo
b2.nameVal
b2.nameVar = "B"
b2.nameVar

输出:

defined class A

defined class B

b1: B = [email protected]9825fab
res0: String = B.foo
res1: String = B
res2: String = A

b2: A = B@c46c4a1
res3: String = B.foo
res4: String = B
b2.nameVar: String = B
res5: String = B

当一个类extends另外一个类的时候,override的规则基本如下:

  • 子类中的方法要覆盖父类中的方法,必须写override(参见foo)
  • 子类中的属性val要覆盖父类中的属性,必须写override(参见nameVal)
  • 父类中的变量不可以覆盖(参见nameVar)

在抽象类中可以不用写override

/*
trait的extent不需要override
*/
trait T {
  def foo : String
  def bar : String
}

class TB extends T {
  def foo: String = {
    "TB.foo"
  }

  def bar: String = "TB.bar"
}

val tb = new TB
tb.foo
tb.bar

trait TT  extends T {
  def bar :String = "TT.bar"
}

class TTB extends TT {
  def foo: String = "TTB.foo"
}
val ttb = new TTB
ttb.foo
ttb.bar

输出:

defined trait T

defined class TB

tb: TB = [email protected]2fb497ea
res6: String = TB.foo
res7: String = TB.bar

defined trait TT

defined class TTB

ttb: TTB = [email protected]346c06af
res8: String = TTB.foo
res9: String = TT.bar

T是特性类,它定义了两个抽象方法,foo和bar。TB的类继承和实现了T特性类,这个时候,TB类中的foo和bar前面的override是可写可不写的。这里初步看下TB类中的foo和bar前面的override写和不写感觉都一样,但是一旦有钻石结构的类继承,这个override的作用就体现出来了。这个我们后续说。

TT和TTB的例子也是说明了下trait继承trait是不需要使用override的。

abstrct class 也不需要使用override

/*
abstrct class 不需要override
*/
abstract class PA(name: String) {
  def hello: String
}

class PB(name: String) extends PA(name) {
  def hello : String = s"hello ${name}"
}

val pb = new PB("yejianfeng")
pb.hello

输出:

defined class PA

defined class PB

pb: PB = [email protected]62840167
res10: String = hello yejianfeng

abstract class和trait的特性主要是在是否有构造参数,在override方面都是一样的。

钻石结构

所谓的钻石结构就是一个菱形的结构,一个基类,两个子类,最后一个类又继承这两个子类。那么如果这两个子类都包含一个基类的方法,那么最后的这个类也有这个方法,选择继承那个子类呢?

/*
钻石结构
*/
trait Animal {
  def talk: String
}

trait Cat extends Animal {
  def talk: String = "I am Cat"
}

trait Monkey extends Animal {
  def talk: String = "I am monkey"
}

trait Dog extends Animal {
  override def talk: String = "I am Dog"
}

val kittyDog = new Cat with Dog
kittyDog.talk

class MonkeyCat extends Monkey with Cat {
  override def talk: String = "I am monkeyCat"
}

val monkeyCat = new MonkeyCat
monkeyCat.talk

输出:

defined trait Animal

defined trait Cat

defined trait Monkey

defined trait Dog

kittyDog: Cat with Dog = $anon$[email protected]5378ef6d
res11: String = I am Dog

defined class MonkeyCat

monkeyCat: MonkeyCat = [email protected]1e444ce6
res12: String = I am monkeyCat

在这个例子中,Animal是基类,Cat和Dog是子类,kittyDog是继承了Cat和Dog,那么kittyDog里面的talk使用的是Cat和Dog中有标示override的那个方法。这个时候override的作用就体现出来了。

参数复写使用override

我们可以直接在构造函数里面使用override重写父类中的一个属性。我理解这个更多是语法糖的一个功能。

/*
参数复写
*/
class Person(val age : Int){
  val name = "no name"
}

class XiaoMing(age: Int, override val name: String) extends Person(age){

}
val xiaoming = new XiaoMing(12, "xiaoming")
xiaoming.name

输出:
defined class Person

defined class XiaoMing

xiaoming: XiaoMing = [email protected]2eef0f3c
res13: String = xiaoming

转自:https://www.cnblogs.com/yjf512/p/8026611.html

最终效果:

原文地址:https://www.cnblogs.com/muailiulan/p/12252695.html

时间: 2024-08-30 05:19:21

Scala实验任务二的相关文章

在Spark上用Scala实验梯度下降算法

首先参考的是这篇文章:http://blog.csdn.net/sadfasdgaaaasdfa/article/details/45970185 但是其中的函数太老了.所以要改.另外出发点是我自己的这篇文章 http://www.cnblogs.com/charlesblc/p/6206198.html 里面关于梯度下降的那幅图片. 改来改去,在随机化向量上耗费了很多时间,最后还是做好了.代码如下: package com.spark.my import org.apache.log4j.{L

Scala实验二——2.模拟图形绘制

题目: 对于一个图形绘制程序,用下面的层次对各种实体进行抽象.定义一个 Drawable 的特 质,其包括一个 draw 方法,默认实现为输出对象的字符串表示.定义一个 Point 类表示点, 其混入了 Drawable 特质,并包含一个 shift 方法,用于移动点.所有图形实体的抽象类为 Shape,其构造函数包括一个 Point 类型,表示图形的具体位置(具体意义对不同的具体图 形不一样).Shape 类有一个具体方法 moveTo 和一个抽象方法 zoom,其中 moveTo 将图形从

Scala实验任务三

统计学生成绩 学生的成绩清单格式如下所示,第一行为表头,各字段意思分别为学号.性别.课程名 1.课程名 2 等,后面每一行代表一个学生的信息,各字段之间用空白符隔开 Id gender Math English Physics 301610 male 80 64 78 301611 female 65 87 58 给定任何一个如上格式的清单(不同清单里课程数量可能不一样),要求尽可能采用函数式编程,统计出各门课程的平均成绩,最低成绩,和最高成绩:另外还需按男女同学分开,分别统计各门课程的平均成绩

scala实验 模拟图形绘制

题目: 对于一个图形绘制程序,用下面的层次对各种实体进行抽象.定义一个 Drawable 的特 质,其包括一个 draw 方法,默认实现为输出对象的字符串表示.定义一个 Point 类表示点, 其混入了 Drawable 特质,并包含一个 shift 方法,用于移动点.所有图形实体的抽象类为 Shape,其构造函数包括一个 Point 类型,表示图形的具体位置(具体意义对不同的具体图 形不一样).Shape 类有一个具体方法 moveTo 和一个抽象方法 zoom,其中 moveTo 将图形从

第五次课后实验

实验5:数组 本次实验是第三次上机,属于验证设计性实验,通过本次实验学生将掌握以下内容: 1. 知道怎么样声明.创建和初始化各种类型的数组 2. 理解二维数组的概念,能够声明.创建和初始化各种类型的二维数组 3. 掌握对一维或二维数组元素的访问方法 4. 掌握不规则二维数组的声明.创建和初始化以及访问的方法了解Arrays类及System类中关于数组操作的方法的使用 [实验任务一]:验证课件例子中源程序并标识不理解的地方(验证型). 1. 实验要求: 1) 调试课件中例子中的源程序代码并分析程序

汇编语言实验五

实验任务一 1.利用debug加载.跟踪程序 (1)先利用r命令来查看各个寄存器的值 (2)从cx中可知道程序的长度,用cx中的值减去20h(数据段和栈段已分配的空间)得到代码段的长度,用u命令精确反汇编 (3)先执行到000D之前,看看ds是否已成功指向数据段 (4)从上图可以看到ds已指向数据段,然后我们接着执行到程序返回前,即到001D之前,再查看一次数据段的内容 (5)从上图可以看到,数据段没有发生变化 2.书上的问题解答: (1)程序返回前,data段中的数据为 23 01 56 04

实验五:编写、调试具有多个段的程序

实验任务一 将下面的程序编译.链接,用debug加载.跟踪,然后回答问题. 1 assume cs:code, ds:data, ss:stack 2 data segment 3 dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h 4 data ends 5 6 stack segment 7 dw 0, 0, 0, 0, 0, 0, 0, 0 8 stack ends 9 10 code segment 11 start: mo

Open vSwitch使用案例扩展实验

实验参考 Open vSwitch使用案例扩展实验 实验步骤 1. 实验任务一. 1.创建新文件ovsSingleBr.py并编辑以下内容: #!/usr/bin/python from mininet.net import Mininet from mininet.node import Node from mininet.link import Link from mininet.log import setLogLevel, info def myNet(): "Create networ

java多态动手动脑

实验任务一:多态实现ATM工作原理 1)源代码: package demo; import java.util.Scanner; class A{ String name; String date; String mima; int yu; String kahao; public A(String name,String date,String mima,int yu,String kahao) { this.name=name; this.date=date; this.mima=mima;