Skip to content
Go back

使用函数式进行面向对象编程

Updated:

使用函数式进行面向对象编程

1. 函数式编程中的一流公民函数

在 Haskell 中,函数是一等公民,这意味着你可以像对待数据一样对待函数。闭包(closure)允许你将状态封装在函数中,而无需显式地使用可变变量。

基本构造函数示例:杯子(Cup)

cup flOz = \\message -> message flOz

获取状态:getOz

getOz aCup = aCup (\\flOz -> flOz)

更新状态:drink

初始版本:

drink aCup ozDrank = cup (flOz - ozDrank)
  where flOz = getOz aCup

改进版本:

drink aCup ozDrank = if ozDiff >= 0
  then cup ozDiff
  else cup 0
  where flOz = getOz aCup
        ozDiff = flOz - ozDrank

模拟多次喝水:foldl

afterManySips = foldl drink coffeeCup [1,1,1,1,1]

2. 更复杂的对象:机器人(Robot)

构造函数

robot (name, attack, hp) = \\message -> message (name, attack, hp)

Getter 函数

getName aRobot = aRobot (\\(n, a, h) -> n)
getAttack aRobot = aRobot (\\(n, a, h) -> a)
getHP aRobot = aRobot (\\(n, a, h) -> h)

Setter 函数

setName aRobot newName = aRobot (\\(n, a, h) -> robot (newName, a, h))
setAttack aRobot newAttack = aRobot (\\(n, a, h) -> robot (n, newAttack, h))
setHP aRobot newHP = aRobot (\\(n, a, h) -> robot (n, a, newHP))

打印机器人信息

printRobot aRobot = aRobot (\\(n, a, h) -> n ++ " attack:" ++ show a ++ " hp:" ++ show h)

3. 对象之间的交互:战斗(Fight)

造成伤害:damage

damage aRobot attackDamage = aRobot (\\(n, a, h) -> robot (n, a, h - attackDamage))

定义战斗逻辑:fight

fight aRobot defender = damage defender attack
  where attack = if getHP aRobot > 10
                 then getAttack aRobot
                 else 0

三回合战斗示例

gentleGiant = robot ("GentleGiant", 10, 100)  -- 假设初始值
killerRobot = robot ("Kill3r", 25, 200)

gentleGiantRound1 = fight killerRobot gentleGiant      -- Kill3r 攻击 GentleGiant
killerRobotRound1 = fight gentleGiant killerRobot      -- GentleGiant 反击 Kill3r
gentleGiantRound2 = fight killerRobotRound1 gentleGiantRound1
killerRobotRound2 = fight gentleGiantRound1 killerRobotRound1
gentleGiantRound3 = fight killerRobotRound2 gentleGiantRound2
killerRobotRound3 = fight gentleGiantRound2 killerRobotRound2

4. 无状态编程的重要性

示例:快慢机器人

fastRobot = robot ("speedy", 15, 40)
slowRobot = robot ("slowpoke", 20, 30)

战斗顺序

slowRobotRound1 = fight fastRobot slowRobot
fastRobotRound1 = fight slowRobotRound1 fastRobot
slowRobotRound2 = fight fastRobotRound1 slowRobotRound1
fastRobotRound2 = fight slowRobotRound1 fastRobotRound1
slowRobotRound3 = fight fastRobotRound2 slowRobotRound2
fastRobotRound3 = fight slowRobotRound3 fastRobotRound2

与有状态编程对比

在面向对象编程(OOP)中:

fastRobot.fight(slowRobot)
slowRobot.fight(fastRobot)

5. 为什么无状态编程重要?


总结

这段代码展示了如何在 Haskell 中使用闭包和函数式编程模拟对象和状态管理。通过 cuprobot 示例,你可以看到无状态编程如何通过生成新对象来“更新”状态,而不修改原有数据。这种方法在并发编程中尤为强大,因为它消除了副作用和顺序依赖的问题。


Suggest Changes

Previous Post
IO
Next Post
类型类