2017-08-19 66 views
0

我正在学习面向对象和函数式编程。我在10分钟内在YouTube上解释OOP发现了这个非常好的简短例子(如果你知道更好的例子,请建议),耶! https://www.youtube.com/watch?v=4c4nP7GLL1c您将如何使用函数式编程编写此代码

现在,我想学习如何编写这段代码的功能性的方式 - 与不变性,不递归循环等

DEMO.PHP 
<?php 
Include_once(“player.php”); 

$p1 = new player(); 
$p1->name = “Brutus”; 
$p1->type = “Warrior”; 
$p1->hitpoints = 100; 

$p2 = new player(); 
$p2->name = “Mysterio”; 
$p2->type = “Sorcerer”; 
$p2->hitpoints = 100; 

$p1->meleeAttack($p2); 
$p2->meleeAttack($p1); 

Echo “<h1> Fight Results</h1>”; 
Echo “<h2>.$p1->name.” now has “.$p1->hitpoints.” hit points</h2>”; 
Echo “<h2>.$p2->name.” now has “.$p2->hitpoints.” hit points</h2>”; 
?> 


PLAYER.PHP 
<?php 
Class player { 

    public $name; 
    public $type; 
    public $hitpoints; 
    public function meleeAttack($target){ 
     $current_hp = $target->hitpoints; // hp is for hitpoints 
     $damage = rand(10,20); 
     if($this->type == “Warrior”) {  // condition logic 
      $damage += 10; 
     } 
     $target->hitpoints = $current_hp - $damage; 
    } 
} 

?> 

干杯, 附:我知道,PHP是不是函数式编程所选择的语言,没有必要提醒吧:)

+2

这不会是非常不同的;你没有循环来取代。基本上,你使'meleeAttack'成为一个以两个玩家为参数的函数,并返回一个新生命值降低的生命值,而不是一个使玩家变异的方法。根据你是否使用纯粹的功能语言,你如何处理随机伤害会有所不同。 – chepner

+0

我不明白,“...返回一个新的玩家......”部分。老玩家会怎么样?程序如何知道哪个播放器是最近的?我需要看到代码:( – user3013157

+0

)除了更新一个包装的属性,你用一个新的对象替换了现有的玩家,除了它有更少的生命点之外,'meleeAttack'变成了一个复制构造器,除了“copy “如果玩家1攻击玩家2,你会写'$ p2 = meleeAttack($ p1,$ p2)'这个函数让攻击者并将其目标作为参数,并返回目标的修改副本 – chepner

回答

4

我将介绍如何利用Haskell做功能编程,因为我不知道PHP:

import System.Random (randomRIO) 

-- Data Declarations 

data Class = Warrior | Sorcerer deriving Eq 

data Player = Player { name  :: String 
        , archetype :: Class 
        , hitpoints :: Int 
        } 

-- Example Data 

p1 :: Player 
p1 = Player "Brutus" Warrior 100 

p2 :: Player 
p2 = Player "Mysterio" Sorcerer 100 

-- Code Section 

meleeAttack :: Player -> Player -> IO Player 
source `meleeAttack` target = do 
    damage <- randomRIO (10, 20) 
    let bonus = if archetype source == Warrior then 10 else 0 
    let newHP = hitpoints target - damage - bonus 
    return target { hitpoints = newHP } 

-- Main Function 

main :: IO() 
main = do 
    p2 <- p1 `meleeAttack` p2 
    p1 <- p2 `meleeAttack` p1 
    putStrLn "Fight Results" 
    putStrLn (name p1 ++ " now has " ++ show (hitpoints p1) ++ " hitpoints") 
    putStrLn (name p2 ++ " now has " ++ show (hitpoints p2) ++ " hitpoints") 

好的,的面向对象的编程和功能编程之间的最大差异,以便一个是代码和数据分离:

  1. 在面向对象的编程代码和数据也不会分开。看看你自己的Player课程。它有三个公共领域和一个在这些领域运作的公共方法。
  2. 在函数式编程中,代码和数据保持分离。我们的数据声明处于程序的开始阶段,随后对这些数据进行操作。

另一个很大的区别是可变性。在面向对象编程中,对象通常是可变的。因此,方法通常会修改现有的对象。在功能编程中,变异被认为是不好的因此,函数通常不会修改任何内容。相反,他们会返回他们操纵的任何数据的更新副本。

例如,考虑meleeAttack函数。它需要两个输入,sourcetarget,它们都是Player数据。输出也是Player数据。这是更新的target。原来的target保持不变。

无论如何,如果你想学习函数式编程,那么你应该阅读Learn You A Haskell

+0

这个Haskel代码是否可以使用类,对象属性和方法以OOP方式编写?我的道歉,我正在学习,我希望看到OOP和功能 – user3013157

+0

在函数式编程中,您不会在* OOP意义上拥有*对象。'Player'数据类型封装了你的PHP类跟踪的状态,而不是更新给定对象的方法,而是编写返回* new *对象的函数,这些对象反映对函数参数的更改。 – chepner