Scala11

Extractor

  • 这一章主要讲 Extractor,extractor使得你可以定义自己的模式,而不用创建对应的 case class,即: Extractor let you define new patterns for preexisting types, where the pattern need not follow the internal representation of the type.

  • An extractor in Scala is an object that has a method called unapply as one of its members. The purpose of that unapply method is to match a value and take it apart. Often, the extractor object will define a method apply for building vlaues, but that’s optional.

  • Whenever pattern matching encounters a pattern referring to an extractor object, it invokes the extractor’s unapply method on the selector expression.

  • The apply method is called an injection, because it takes some arguments and yields an element of a given set. The unapply method is called an extraction, because it takes an element of the same set and extracts some if its parts.

  • 定义 unapplySeq ,这样就可以匹配任意长的参数了

  • 在模式匹配中,我们可以使用 sequence patterns 来匹配 List或者 Array是像 scala.List

companion object is an extractor that defines an unapplySeq method. unapplySeq method that returns all elements of the list as a sequence. That’s what supports List(…) patterns.

Extractors versus case classes
  • case class的缺点在于:They expose the concrete representation of data. This means that the name of the class in a constructor pattern corresponds to the concrete represetation type of the selector object.

  • Extractor具有 representation independence,所以不存在这样的问题

  • 不过case class也有自己的好处: First, they are much easier to set up and to define, and they require less code. Second, they usually lead to more efficient pattern matches than extractor. Third, if your case classes inherit from a sealed base class, the Scala compiler will check your pattern matches for exhaustiveness and will complain if some combination of possible vlaues is not covered by a pattern.

Regular expressions
  • 正则表达式有定义 unapplySeq 方法,利用这个方法,可以按组将已匹配的文本提取出来
Conclusion
  • Extractors let you define your own kinds of patterns, which need not correspond to the type of the expressionyou select on.This gives you more flexibility in the kinds of patterns you can use for matching. In effect it’s like having different possible views on the same data. It also gives you a layer between a type’s representation and the way clients view it. This lets you do pattern matching while maintaining representation independence, a property which is very useful in large software systems.

  • 感觉 extractor 也是一个好用的工具,不过自己现在还是理解的模模糊糊的,还是要写写代码来理解

Annotations

  • 这一章主要讲什么是注解以及为什么需要注解,不涉及如何设计自己的注解

  • Annotations are structrured information added to program source code.

  • 注解被称为所谓的元编程工具。对于Scala编译器来说,The compiler understands just one feature, annotations, but it doesn’t attach any meaning to individual annotations.

  • Annotations are allowed on any kind of declaration or definition, including vals, vars, defs, classes, objects, traits and types

  • 注解的一般形式如下:

@annot(exp1, exp2, ...) { val name1=const1, ... }

The annot specifies the class of annotation. All annotations must include that much. The exp parts are arguments to the annotation.

Standard annotations
  • Deprecation

  • Volatile fields

  • Binary serialization

  • Automatic get and set methods – 添加了这个注解后,编译器会把你生成 get 和 set 方法,但是要注意这些 get 和 set 方法只有在编译完成后才能使用

  • Unchecked – It tells the compiler not to worry if the match expression seems to leave out some cases.

Object Equality

  • 这一章主要介绍定义自己的 equals 以及 hashCode 方法,给出错误的案例以及一些原则

  • 在Scala中,== 都是用来比较值的,如果需要比较对象那么就可以使用 eq 方法

  • 默认 == 是使用 equals 方法实现的,可以通过覆盖 equals 方法来重新定义 == 的行为,但是

不可以覆盖 == 方法

实现 equals 方法常犯的四种错误
Defining equals with the wrong signature
  • 如果需要覆盖 equals 方法,那么要注意 equals 接受的参数类型是 Any,如果错误的使用了

其他类型,那么就不是覆盖 equals 方法,而只是进行了重载

Changing equals without also changing hashCode
  • 如果不覆盖 hashCode 方法,那么默认 hashCode 实现是使用对象的内存地址作为哈希值。

所以,一般地覆盖了 equals 方法后还需要覆盖 hashCode 方法

Defining equals in terms of mutable fields
  • 使用 mutable field 会给对比带来一定的麻烦,特别是哈希值的计算。如果对比 mutable field,那么

就不建议使用 equals 来实现

Failing to define equals as an equivalence relation
  • The contract of the equals must implement as equivalence relation on non-null objects:

    1. It is reflexive

    2. It is symmetric

    3. It is transitive

    4. It is consistent

    5. For any non-null value x, x.equals(null) should return false

  • 对于有继承关系的类,可以定义canEqual(利用isInstanceof)方法,决定父类与子类能否相等

Defining equality for parameterized types
  • 给参数化类型的对象定义 equals 方法,不过这里要注意的是:Scala会在编译期擦除类型信息,所以运行时

是无法知道类型信息的。可以使用existential type表示一个未知的类型,表示匹配任意的参数类型

Recipes for equals and hashCode
Below are the recipe for overriding equals
  • If you’re going to override equals in a non-final class, you should create

a canEqual method. If the inherited definition of equals is from AnyRef

, the definition of canEqual will be new, otherwise it will override a previous

definition of a method with the same name. The only exception to this requirement is

for final classes that redefine the equals method inherited from AnyRef

  • The canEqual method should yield true if the argument object is an instance

of the current class, false otherwise.

  • In the equals method, make sure you declare the type of the object passed

as an Any

  • Write the body of the equals method as a single match expression.

The selector of the match should be the object passed to equals

  • The match expression should two cases. The first case should declare

a typed pattern for the type of the class on which you’re defining the equals method

  • In the body of this case, write an expression that logical-ands together the

individual expressions that must be true for the objects to be equal

  • For the second case, use a wildcard pattern that yields false
Below are the recipe for overriding hashCode
  • Include in the calculation each field in your object that is used to determine

equality in the equals method

  • For each relevant field, no matter its type, you can calculate a hash code by

invoking hashCode on it.

  • If the equals method invokes super.equals(that) as part of its calcuation,

you should start your hashCode calculation with an invocation of super.hashCode

Conclusion
  • In retrospect, defining a correct implementation of equals has been surprisingly

subtle. You must be careful about the type signature; you must override hashCode;

you should avoid dependencies on mutable state; and you should implement and use

a canEqual method if your class is non-final.

  • Given how difficult it is to implement a correct equality method, you might

prefer to define your classes of comparable objects as case classes. That way,

the Scala compiler will add equals and hashCode methods with the right

properties automatically

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值