Scala 中 object、class 与 trait 的区别

引言

当你刚入门 Scala,肯定会迫不及待想要编写自己的第一个 Scala 程序。如果你已经在交互模式下敲过 Scala 代码,想必你更乐意尝试在 IDEA 下写 Scala 代码。当你打开 IDEA,满心期待的创建自己的第一个 Scala 工程,接着创建一个 Scala 类,如下:

你会发现这里有好几种类型,如果你之前学过 Java,你会毫不犹豫选择第一个 Class 类型,然后快速写下如下代码:

class MyFirstScala {
def main(args: Array[String]): Unit = {
prinln("hello scala")
}
}

当你正打算运行这个 main 方法时,却发现无法执行,我猜你肯定当时就郁闷了。

要让 main 方法执行其实很简单,只需要将 class 改为 object 即可,如下:

object MyFirstScala {
def main(args: Array[String]): Unit = {
prinln("hello scala")
}
}

这到底是怎么回事呀?

object

单例对象概念

我们都知道 Scala 与 Java 一样,是一种面向对象的编程语言;但是 Scala 却与 Java 有所不同,就是 Scala 具有直接创建对象的能力,该对象无需类即可定义其成员

什么意思呀?就是不需要定义 class 类,也不需要 new,就能直接创建一个对象。而且创建对象的方式和定义类的方式是一样的,唯一的区别就是创建对象要使用 object 关键字。

通过 object 直接创建的对象,我们称为单例对象。 为何叫单例对象,因为单例对象是没有类就可以存在的对象,这样的对象是独一无二的,不像通过 class 方式可以 new 无数的对象。

那为何 Scala 中程序入口 main() 方法一定要放在 object 创建的单例对象中执行,而不能像 Java 一样?

许多面向对象的编程语言包括 Java 都是使用 static 关键字修饰 main() 方法,这样 main() 方法就变成了类静态方法,这样在类加载完成后就可以直接调用 main() 方法了。

但是,Scala 根本就没有 static 关键字, 也没有类静态方法和静态属性。这就是为什么在 Scala 中 main() 方法只能放在 object 定义的单例对象中执行。

单例对象定义
object singleton_objname {
// object code , member functions and fields.
}

注意:object 不能提供构造器参数,也就是说 object 必须是无参的

单例对象用法
object findsum{
var a = 56
var b = 21
def sum(): Int ={
return a+b;
}
} object Main
{
def print(){
printf("The sum is : "+ findsum.sum());
}
def main(args: Array[String])
{
print();
}
}
伴生对象和伴生类

如果类和单例对象具有相同的名称,那么该类为该对象的同伴类,而该对象为该类的伴生对象

伴生对象与伴生类在 Scala 的面向对象编程方法中占据极其重要的位置,主要用于代替 Java 静态成员变量与静态方法,很多 Scala 工具方法都是采用单例对象或伴生对象实现的。

伴生类与伴生对象可以互相访问彼此的私有属性或方法,但是必须都在同一源文件

class companion{
var a = 23;
var b = 78;
def sum(){
println("The sum is: "+ (a+b));
}
} object companion{
def main(args:Array[String]){
new companion().sum();
}
}

class

Scala 是一种面向对象的编程语言,所以其定义和使用类的方式和 Java 基本相同,不过 Scala 也有一些不同的地方之处

构造器
  • 主构造器

    Scala 中每个类都有且只有一个主构造器,且主构造器会执行类定义中的所有语句

    class Student(val name: String,val age: Int){   // 括号中的就是主构造器的参数
    println("Primary constructor") // 该语句属于主构造器的一部分
    ...
    }

    只有主构造器的参数才会被编译成字段,其初始化的值为构造时传入的参数。

    可以在主构造器中使用默认参数,可防止辅助构造器使用过多。

    class Student(val name: String = "",val age: Int = 0){   // 主构造器的默认参数
    ...
    }
  • 辅助构造器

    辅助构造器的名称为 this

    class Student {
    private var name = " "
    private var age = 0 def this(name: String){ //辅助构造器1
    this() //调用主构造器
    this.name = name
    } def this(name: String,age: Int){ //辅助构造器2
    this(name) //调用前一个辅助构造器
    this.age = age
    }
    }

    每个辅助构造器都必须以一个对先前已定义的其他辅助构造器或主构造器的调用开始

  • 私有构造器

    想要让主构造器变成私有构造器,只需要加上 private 关键字即可

    class Dog private(val age: Int) {
    ...
    }

    这样做之后,就必须使用辅助构造器来构造 Dog 对象了

属性(成员变量)

scala 对每个类属性或成员变量都会提供 getter 和 setter 方法,同时也可以显示的声明,但是针对 val 类型,只提供getter 方法,默认情况下,字段为 public 类型

trait

在 Scala 中 trait(特征) 相当于 Java 的接口,与接口不同的是它还可以定义属性和方法的实现,这一点又更像 Java 的抽象类。

一般情况下 Scala 的类只能够继承单一父类,但是如果是 trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承。

trait Person {
def getInfo(): String
} class Man(var name: String, var age: Int) extends Person {
override def getInfo(): String = {
s"info:name=${name},age=${age}"
}
}

总结

在 Scala 中,object 用于定义单例对象,class 用于定义类,trait 用于定义接口。至于还有两个 case class / case object 类型,主要用于支持模式匹配。

Scala 中 object、class 与 trait 的区别的更多相关文章

  1. html中object和embed标签的区别

    ♦object定义一个嵌入的对象.请使用此元素向您的 XHTML 页面添加多媒体.此元素允许您规定插入 HTML 文档中的对象的数据和参数,以及可用来显示和操作数据的代码. ♦<object&g ...

  2. Scala中 object 和 class的区别

    object 在scala中没有静态方法和静态字段,所以在scala中可以用object来实现这些功能,直接用对象名调用的方法都是采用这种实现方式,例如Array.toString.对象的构造器在第一 ...

  3. Scala 中object和class的区别

    Scala中没有静态类型,但是有有“伴侣对象”,起到类似的作用. Scala中类对象中不可有静态变量和静态方法,但是提供了“伴侣对象”的功能:在和类的同一个文件中定义同名的Object对象:(须在同一 ...

  4. Scala 中的函数式编程基础(三)

    主要来自 Scala 语言发明人 Martin Odersky 教授的 Coursera 课程 <Functional Programming Principles in Scala>. ...

  5. Spark基础-scala学习(三、Trait)

    面向对象编程之Trait trait基础知识 将trait作为接口使用 在trait中定义具体方法 在trait中定义具体字段 在trait中定义抽象字段 trait高级知识 为实例对象混入trait ...

  6. (数据科学学习手札46)Scala中的面向对象

    一.简介 在Scala看来,一切皆是对象,对象是Scala的核心,Scala面向对象涉及到class.object.构造器等,本文就将对class中的重点内容进行介绍: 二.Scala中的类 2.1 ...

  7. scala class和object,trait的区别

    Scala类 1 2 3 4 5 6 7 8 9 10 11 12 13 class Counter {   private var value = 0 // 必须初始化字段   def increm ...

  8. scala 学习笔记(05) OOP(中)灵活的trait

    trait -- 不仅仅只是接口! 接上回继续,scala是一个非常有想法的语言,从接口的设计上就可以发现它的与众不同.scala中与java的接口最接近的概念是trait,见下面的代码: packa ...

  9. 第2节 Scala中面向对象编程:12、13、14、15、16、trait

    6.4.  Scala中面向对象编程之trait 6.4.1.    将trait作为接口使用 Scala中的trait是一种特殊的概念: 首先先将trait作为接口使用,此时的trait就与Java ...

随机推荐

  1. CMD控制台(命令提示符)的打开方式

    打开CMD的方式 打开+系统+命令提示符 Win键 +R 输入cmd 打开控制台(推荐使用) 在任意的文件夹下面,按住shift键+鼠标右键点击+在此处打开命令行窗口 资源管理器的地址栏前面加上cmd ...

  2. Semaphore自白:限流器用我就对了!

    大家好,我是 Semaphore,我的中文名字叫"信号量",我来自 JUC(java.util.concurrent)家族. 我们家族有很多优秀的成员,比如:CountDownLa ...

  3. (十七)VMware Harbor 垃圾清理

    1. 在线垃圾清理 注意:从Harbor中删除镜像时不释放空间,垃圾收集是通过从清单中不再引用文件系统中删除blob来释放空间的任务. 注意:在执行垃圾收集时,Harbor将进入只读模式,并且禁止对d ...

  4. 官宣 MAUI 在.NET Preview 3的最新进展

    我们在.NET 6 Preview 3中交付了.NET多平台应用UI的移动和桌面开发的最新进展.此版本添加了Windows平台和WinUI 3,改进了基本应用程序和启动构建器,添加了原生生命周期事件, ...

  5. SpringBoot自定义配置以及IDEA配置提示

    本篇文章将会讲解在springboot项目中如何实现自定义配置以及在IDEA或者Eclipse中实现配置项提示,就像spring的配置提示一样 想要做到这点其实非常简单 1.添加依赖 <depe ...

  6. php和mysql数据库防SQL注入的有效解决办法

    <?php$mysqli = new mysqli("localhost", "my_user", "my_password", &q ...

  7. POJ3692 最大点权独立集元素个数

    题意:      n个男孩和m个女孩,给你他们谁和谁彼此了解,问你要找到一个集合,使得这个集合中的男孩和女孩相互了解,并且人数最多. 思路:      简单题目,其实就是在求最大点权独立集元素个数,先 ...

  8. hdu5007 小水题

    题意:       给你一个串,如果出现子串 "Apple", "iPhone", "iPod", "iPad"输出MA ...

  9. Tomcat管理弱口令页面Getshell

    目录 弱口令Getshell 利用Burpsuite对tomcat账号密码进行爆破 弱口令Getshell Tomcat安装完成后会有如下页面,点击该页面的 Manager App 处会弹出输入用户名 ...

  10. Windows 签名伪造工具的使用,Python,签名

    #!/usr/bin/env python3 # LICENSE: BSD-3 # Copyright: Josh Pitts @midnite_runr import sys import stru ...