2017-08-19 69 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