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. create-react-app 核心思路分析

    原文链接:http://axuebin.com/articles/fe-solution/cli/cra.html,转载请联系 Create React App is an officially su ...

  2. 告别DNS劫持,一文读懂DoH

    如果评选一个差评服务器榜单,除去育碧高居榜首外,一定也少不了 Nintendo Switch 让人头秃的联网服务.尽管任天堂已经架设了香港 CDN 服务器用于加速,但是更新安装的速度也没有什么大幅改变 ...

  3. 安卓to鸿蒙系列:Timber

    目录 Guide 原理 知识点 移植到鸿蒙 Guide 本文基于https://gitee.com/andych008/timber_ohos 分析Timber的源码,及移植到鸿蒙需要做的工作. 大神 ...

  4. UT之最后一测

    经过前面几次文章的分享的UT的相关知识,今天接着分享UT相关最后一测文章,希望对大家在UT的学习中有一点点的帮助. Spring集成测试 有时候我们需要在跑起来的Spring环境中验证,Spring ...

  5. 6- MySQL条件查询与通配符

    -数据库表中一般包含大量的数据,很少需要查询表中的所有行,通常只会根据特定的需要提取表中的一部分数据.这个时候需要制定查询条件,及过滤条件. -在select语句中,数据库根据where字句中指定的查 ...

  6. hdu4499 搜索

    题意:       给你一个棋盘,最大是5*5的,问你最多可以放多少个炮,炮和炮之间不可以相互攻击,这块只的是只能走一步,不存在两个炮中间三个棋子的情况.. 思路:    刚开始想的是把所有的空位置都 ...

  7. UVA11384正整数序列(把123..变成0的最小步数)

    题意:      给定一个正整数n,你的任务是最少的操作次数把序列1 2 3 4 5...n中所有的数字都变成0,每次操作可以从序列中选择一个活多个整数,同时减去一个相同的正整数,比如 1 2 3可以 ...

  8. UVA10780幂和阶乘

    题意:       输入两个整数n,m(1<m<5000,0<n<10000)求最小的k使得m^k是n!的因子. 思路:      比较容易想,一开始手残wa了好几次,我们直接 ...

  9. 用户模式下的线程同步的分析(Windows核心编程)

    线程同步 同一进程或者同一线程可以生成许多不同的子线程来完成规定的任务,但是多个线程同时运行的情况下可能需要对某个资源进行读写访问,比如以下这个情况:创建两个线程对同一资源进行访问,最后打印出这个资源 ...

  10. Win64 驱动内核编程-18.SSDT

    SSDT 学习资料:http://blog.csdn.net/zfdyq0/article/details/26515019 学习资料:WIN64内核编程基础 胡文亮 SSDT(系统服务描述表),刚开 ...