Scala学习笔记(四) 类的初步Scala 类相关总结

Scala 类相关

终于来到面向对象的地方了,虽说函数式编程是 Scala 的特性,让人们觉得 Scala 是更好的 Java。但是在架构层面上一直提倡着:小处用函数式编程,大处用面向对象编程。

从这篇笔记开始,会记录类的相关内容。由于类相关的内容比较多,我可能会整理几篇文章来写。

1. 构造器

在 java 中定义一个简单的用户类,以及构造函数

public class User {

    private String name;
    private String password;
    
    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

然而在 Scala 中,只需一代码即可跟上面的 Java 代码等价。

scala> class User(var name:String,var password:String)
defined class User

然后创建一个 User 对象。

scala> val tony = new User("tony","123456")
tony: User = User@6a0659ac

也可以用 case 类来推断出构造方法的参数都是val类型的

scala> case class ImmutableUser(name:String,password:String)
defined class ImmutableUser

scala> val user = ImmutableUser("tony","123456")
user: ImmutableUser = ImmutableUser(tony,123456)

稍后,就会讲到case class。

2. 单例对象、伴生对象、Case Class、Trait

2.1 单例对象

Scala学习笔记(二)中,讲述过Scala 中没有静态修饰符 static,在 object 下的成员全部都是静态的,而且 object 不能提供构造器参数。

那么,今天再补充一下,以 object 关键字定义的对象是一个单例对象。

先上一段代码。

scala> object Singleton {
     |  def test() = println("test singleton")
     | }
defined object Singleton

scala> Singleton.test()
test singleton

经过查看 class 文件获取它的源码,Singleton 生成了一个懒汉模式的单例类。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

import scala.Predef.;

public final class Singleton$ {
    public static final Singleton$ MODULE$;

    static {
        new Singleton$();
    }

    public void test() {
        .MODULE$.println("test singleton");
    }

    private Singleton$() {
        MODULE$ = this;
    }
}

2.2 伴生对象

如果在类中声明了与该类相同的名字的 object 则该object 是该类的“伴生对象”。

相对于伴生对象,单独的 object 对象是独立对象(Standalone Object)。他们的主要用途是可以用于工具类,或者定义 Scala 程序的入口等等。

来看一个伴生对象和伴生类使用的例子。

/**
  * Created by tony on 2017/2/20.
  */
class User(var name:String,var age:Int) {

  def greet: Unit = {
    println("hi, My name is "+name)
  }

  override def toString: String = {

    "name is "+ name + ", age is " + age
  }
}

object User {

  def addAge(u: User) = u.age +1
}

object Main extends App {

  //伴生对象可以引用类的私有变量
  val user = new User("Tony",20)
  println(user.age)          //  20
  user.age = User.addAge(user)

  //类可以引用伴生对象的私有变量
  user.greet                 //  hi, My name is Ton

  println(user)              //  name is Tony, age is 20
}

2.3 Case Class

case class 跟普通 class 的区别在于

  • 初始化的时候不需要 new
  • 自动创建伴生对象
  • 默认是可以序列化的,实现了 Serializable
  • 构造函数的参数都是 val 类型的
  • 支持模式匹配。
  • 实现自己的 toString、hashCode、copy、equals 方法
scala> case class User(name:String,age:Int)
defined class User

scala> val tony = User("Tony",20)
tony: User = User(Tony,20)

scala> tony.age = 21
<console>:14: error: reassignment to val
       tony.age = 21
                ^

模式匹配,后面的文章会讲到。

2.4 Trait

Scala 不提供接口,而提供类似接口的 Trait ,跟接口不同的是 Trait 可以写方法的实现。这一点跟 Java 8 接口的默认方法很相似。

scala> trait Fly {
     |  def fly()
     | }
defined trait Fly

scala> trait Swim {
     |   def swim()
     | }
defined trait Swim

scala> class Duck extends Swim {
     |    def swim() {
     |       println ("duck can swim")
     |    }
     | }
defined class Duck

scala> class Swan extends Swim with Fly {
     |   def swim() {
     |      println ("swam can swim")
     |  }
     | 
     |  def fly() {
     |      println ("swam can fly")
     |  }
     | }
defined class Swan

scala> val swam = new Swan()
swam: Swan = Swan@1d0d6318

scala> swam.swim()
swam can swim

scala> swam.fly()
swam can fly

scala> 

定义两个Trait,“飞”和“游泳”。再定义两个类,“鸭子”和“天鹅”。鸭子会游泳,而天鹅既会游泳,也会飞。

对于 Trait 不止一个的类的时候,可以用 with 关键字来添加额外的 Trait。

例如:

extends Trait1 with Trait2 with Trait3

3. 继承

像 Java 一样,Scala 只支持单一继承,而不是多重继承。

总结

本篇内容只是 Scala 类相关内容的开头,后续会陆续整理。

先前的文章: Scala学习笔记(三) Scala学习笔记(二) Scala学习笔记(一)

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏博客园

Core官方DI解析(4)--CallSiteRuntimeResolver

​ CallSiteRuntimeResolver类型是一个创建或获取服务实例的类型,这个类型继承了CallSiteVisitor<TArgument, TRe...

961
来自专栏开发与安全

算法:静态查找表(Static Search Table)(顺序查找、二分查找、插值查找、斐波纳契查找)

查找表(Search table)是由同一类型的数据元素(或记录)构成的集合。关键字(key)是数据元素中某个数据项的值,又称为键值,用它可以表示一个数据元素,...

2415
来自专栏闻道于事

Java I/O流输入输出,序列化,NIO,NIO.2

2543
来自专栏AhDung

【手记】注意BinaryWriter写string的小坑——会在string前加上长度前缀length-prefixed

之前以为BinaryWriter写string会严格按构造时指定的编码(不指定则是无BOM的UTF8)写入string的二进制,如下面的代码:

2753
来自专栏钟绍威的专栏

SpringMVC类型转换器、属性编辑器PropertiesEditor源码分析CustomDateEditor源码分析TypeConverterDelegate源码分析

对于MVC框架,参数绑定一直觉得是很神奇很方便的一个东西,在参数绑定的过程中利用了属性编辑器、类型转换器 参数绑定流程 参数绑定:把请求中的数据,转化成指定类型...

2158
来自专栏小小挖掘机

来学习几个简单的Hive函数啦

咳咳,今天来介绍一下几个Hive函数吧,先放一张我登哥划水的照片,希望大家也做一只自由的鱼儿,在知识的海洋里游呀游,嘻嘻! ? 今天我们来介绍几个Hive常用的...

4334
来自专栏swag code

XML中节点类型

该 Node 接口是整个文档对象模型的主要数据类型。它表示该文档树中的单个节点。当实现 Node 接口的所有对象公开处理子节点的方法时,不是实现 Node 接口...

1276
来自专栏开发与安全

《linux c 编程一站式学习》课后部分习题解答

1、假设变量x和n是两个正整数,我们知道x/n这个表达式的结果要取Floor,例如x是17,n是4,则结果是4。如果希望结果取Ceiling应该怎么写表达式呢?...

4336
来自专栏一枝花算不算浪漫

[Java Collection]List分组之简单应用.

3215
来自专栏ppjun专栏

Android十八章:Java硬软弱虚引用,GC回收,内存碎片

又叫java虚拟机栈区,是每一个方法被执行的时候,创建出一个栈帧用来放的成员变量,操作链表,动态链接,方法出口。很多个栈帧又存储在栈区。

1422

扫码关注云+社区

领取腾讯云代金券