1.4.2 理解使用不可变性的代码

728 篇文章 1 订阅
349 篇文章 0 订阅

1.4.2 理解使用不可变性的代码

 

在前面介绍函数式风格的好处时,我们讨论过不可变性(immutability)。我们使用的示例是一个带边框的椭圆,但是代码的具体行为并不清楚。当我们用不可变对象重写了代码以后,它就变得更容易理解。在后面的章节中,我们会回到这个主题并更详细地讨论。此示例的目的是显示在实践中不可变的对象的表现。

再次强调,如果你在此时没能全部掌握,也不要担心。想象一下,我们正在编写一个游戏,其中的角色就是我们的目标,角色可以用类来表示,下面的清单是这个类的一部分:

 

Listing 1.7 Immutable representation of agame character (C#)

 

classGameCharacter

{

  readonlyint health;           |[1] 把所有字段声明为只读

  readonly Point location;       |

  public GameCharacter(int health, Pointlocation)

  {

    this.health = health;         |[2] 初始化不可变字段

    this.location =location;     |

  }

  publicGameCharacter HitByShooting(Point target)

  {

    int newHealth =CalculateHealth(target);            |[3] 返回更新过健康值的游戏角色

    returnnewGameCharacter(newHealth, this.location); |

  }

  publicbool IsAlive

  {

    get { return health > 0; }

  }

  // Other methods and properties omitted

}

 

在 C# 中,我们可以明确地把字段标记为不可变,用 readonly 关键字,这样,就不能改变字段的值;但是,如果该字段指向非不可变的类[ 即,引用可变类 ],目标对象仍然可以修改。要创建真正不可变的类,需要确保所有字段都被标记为 readonly,且字段的类型都是基本类型、不可变的值类型,或其它不可变的类。

根据这些条件,GameCharacter 类是不可变的,其所有的字段都用 readonly 限定符标记[1],int 是不可变的基本类型,Point 是不可变的值类型。当字段是只读时,值只能在创建对象时才可以设置,因此,我们只能在构造函数中设置角色的位置与健康值[2]。这样,对象初始化之后,就不能修改它的状态。那么,当操作需要修改游戏角色的状态时,我们该怎么做呢?

当你看到 HitByShooting 方法时,就知道答案了[3],它实现了游戏中对开枪的反应。它使用 CalculateHealth 方法(不在此示例中)来计算角色新的健康值。用命令式风格,这需要修改角色的状态,但这里是不可能的,因为类型是不可变的。相反,这个方法创建了GameCharacter 新的实例,表示修改后的角色,作为结果返回。

前面示例中的类,是不可变的 C# 类的典型设计,我们在书中一直使用这个示例(有一些修改)。现在,我们已经知道了不可变类型的表象,有必要了解一下其影响。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值