8、Scala类class

本文详细介绍了Scala中的类(class)概念,包括如何定义类、实例化对象,以及类的扩展和方法重写。示例展示了如何创建包含变量和方法的类,如何通过`override`关键字重写方法,以及子类如何继承和扩展父类的方法。通过这些例子,读者可以深入理解Scala中的面向对象编程特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文介绍Scala中的类class。

1、基本知识

类Classes是一个静态的模版,任何的对象object都可以在执行的时候初始化一个类实例。

就是说类只是一个模版,它要在object中调用实例才会被执行。

class的实例化使用关键字new。

2、class类的定义方法

2.1  通过关键字class来定义类。

类中变量的声明和初始化通过关键字 val /var,这是一样的。

类中方法的定义也是通过关键字 def。

类中方法的重写通过关键字 override def 。

//in scala
/** 定义一个class,声明变量,写方法,重写方法*/
class Student(val m1:Int,val m2:Int) {
  var total:Int = m1 + m2
  var ma1:Int = m1
  var ma2:Int = m2
  def calculateTotal(ma1:Int,ma2:Int) {
    total = ma1 + ma2
    println("Total is :"+total)
  }
  override def toString(): String = "(" + total + ")";
}

2.2 类的实例化

//in scala
object Test {
  def main(args:Array[String]) {
    val student = new Student(72,65); //类的实例化使用关键字 new
    student.calculateTotal(72,65);  //类中方法的调用
    println(student) //注意这里调用的方法和生成的结果
  }
}

3、类的扩展(或方法重写)

类class是可以扩展的(使用关键字extends 进行扩展),但有两个约束条件:首先,只有子类的主构造函数可以将参数传递给父类的构造函数,其次,必须指定override关键字

(注:关于子类、父类,有的语言中叫做派生类、基类,虽然叫法不同但表述的都是同一个内容。)

 3.1 子类重写父类中的方法

注意在子类的主构造函数中 多了两个变量m3,m4,另外子类中的变量m1,m2前面加上了 override方法用于将参数传递给父类的构造函数。

//in scala

class CollegeStudent(override val m1:Int,override val m2:Int,val m3:Int,val m4:Int) extends Student(m1,m2) {
  var ma3:Int = m3
  var ma4:Int = m4
  var tot:Int = 0;
  
  override def calculateTotal( ma1:Int, ma2:Int) {
    tot = ma1 * ma2
    println("Total is :"+tot)
  } //calculateTotal 这个方法名字、参数都与父类中的方法一样,但计算方法是重写的,可以用override关键字
  override def toString():String = "(" + tot + ")";  //这也是一个重写的方法
}

object Test {
  def main(args:Array[String]) {
    val total = new CollegeStudent(72,65,85,60);
    total.calculateTotal(72,65);
    println("Grand Total Marks of the Student is"+total)
  }
}

3.2 子类继承父类中的方法

//in scala
class CollegeStudent(override val m1:Int,override val m2:Int,val m3:Int,val m4:Int) extends Student(m1,m2) {
  var ma3:Int = m3
  var ma4:Int = m4
  var tot:Int = 0;
  //calculateTotal 这个方法是子类中重写的
  override def calculateTotal( ma1:Int, ma2:Int) {
    tot = ma1 * ma2
    println("Total is :"+tot)
  }
  //override def toString():String = "(" + tot + ")"; //删掉这条重写的方法,直接继承父类的方法
}

object Test {
  def main(args:Array[String]) {
    val total = new CollegeStudent(72,65,85,60);
    total.calculateTotal(72,65); //注意这里的方法是重新写过的,调用该方法会生成一个乘法的 tot
    println("Grand Total Marks of the Student is"+total) //注意这里的方式是父类中的,调用该方法生成的是一个加法的 tot
  }
}

注意:子类 CollegeStudent 中的方法 calculateTotal( ma1:Int, ma2:Int) 是父类中方法的继承,它们具有完全相同的方法名、参数个数。

所以,如果要重写该方法必须要加上关键字override,否则会报错。

只要保持方法名、参数个数和参数类型跟父类一致,即使你更改了参数名,也是一样会报错,提示你必须使用override关键字。

如果你想使用跟父类中相同的方法名,但使用不同的参数个数、或者相同的参数个数但参数类型不同,这样子类中的方法就会变成跟父类中方法名一样,但却不同的方法。

这样就可以不使用override关键字。这在下面中进行介绍。

 

3.3 在子类中写父类中没有的方法

在子类中写父类中没有的方法,一般认为是写具有不同名字的方法,这是最常见常规的。

当然也可以使用父类中已有方法的名字,那么既然要是不同于父类的方法,那就要求 要么变量的个数是不同的、要么变量的类型是不同,这样才会成为不同的方法函数。

否则如果方法名、参数个数和命名等都相同,那就直接override重写就是了。

//in scala
class CollegeStudent(override val m1:Int,override val m2:Int,val m3:Int,val m4:Int) extends Student(m1,m2) {
  var ma3:Int = m3
  var ma4:Int = m4
  var tot:Int = 0;
  //  calculateTotal 这个方法虽然名字与父类中的方法一样,但是却不是父类中方法的扩展,即不能加关键词override,因为方法的参数不同,他们是不同的两个方法
  def calculateTotal( ma1:Int, ma2:Int, ma3:Int,  ma4:Int) {
    tot = ma1 + ma2 + ma3+ ma4
    println("Total is :"+tot)
  }
  override def toString():String = "(" + tot + ")";
}

object Test {
  def main(args:Array[String]) {
    val total = new CollegeStudent(72,65,85,60);
    total.calculateTotal(72,65,85,60); //注意这里传入的参数的个数
    println("Grand Total Marks of the Student is"+total)
  }
}

注意:子类 CollegeStudent 中的方法 calculateTotal( ma1:Int, ma2:Int, ma3:Int, ma4:Int) 不是父类中方法的继承或重写,它是完全不一样的方法,因为他们的参数个数不同。

如果我只因为它们使用了相同的方法名就认为是方法的重写,而在其前面加上 override关键字,这是会报错的。

 

 

### Scala 的定义和使用 #### 定义Scala 中,可以通过 `class` 关键字来定义。与 Java 不同的是,默认情况下所有的成员都是公有的,并且不需要显式的访问修饰符。 ```scala // 定义一个简单的 Person class Person(val name: String, var age: Int) { def greet(): Unit = println(s"Hello, my name is $name and I am $age years old.") } ``` 这里定义了一个名为 `Person` 的,它有两个字段:`name` 和 `age`。其中 `val` 表明这个属性是不可变的,而 `var` 则表示可变属性。还定义了一个方法 `greet()` 来打印一条问候消息[^1]。 #### 构造器 Scala 支持主构造器和辅助构造器的概念。上面的例子中已经展示了主构造器的应用方式——直接放在头后面的参数列表即为主构造器的一部分。如果需要更多的初始化逻辑,则可以在大括号内编写相应的代码。 对于辅助构造器来说,可以利用 `this` 关键字创建多个重载版本: ```scala class Student(name: String, age: Int, val grade: Char) extends Person(name, age){ // 辅助构造器 def this(name: String, age: Int){ this(name, age,'A') // 调用了主构造器 } override def greet(): Unit ={ super.greet() println(s"I'm studying in Grade ${grade}.") } } ``` 这段代码展示了一个继承自 `Person` 的子 `Student`,并实现了自己的辅助构造器以及覆写了父的方法 `greet()`。 #### 使用 一旦定义好了之后就可以实例化对象了。这通常只需要简单地提供必要的参数给构造器即可完成操作。 ```scala val person = new Person("Alice", 30) person.greet() val student = new Student("Bob", 20, 'B') student.greet() ``` 上述两行分别创建了 `Person` 及其派生出来的 `Student` 实例,并调用了它们各自的 `greet()` 方法。 #### 抽象 当某些功能无法具体实现时,可以选择将其声明为抽象函数或抽象。这样做的好处是可以强制任何具体的子都必须给出这些未实现部分的具体实现形式。 ```scala abstract class AbstractAdd { def add(x: Int, y: Int): Int // 抽象方法 } class ConcreteAdd extends AbstractAdd { override def add(x: Int, y: Int): Int = x + y // 子提供了具体实现 } ``` 在这个例子中,`AbstractAdd` 是一个带有抽象方法 `add` 的抽象;而 `ConcreteAdd` 继承自前者并且给出了实际的操作细节[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值