2011-10-27 16 views
7

回想一下我的Scala代碼,我注意到它是功能性的或面向對象的。如何混合顯然不兼容的範例:OOP和FP?

事實上,我不知道如何調和由不可變類型和純函數所暗示的無副作用規則以及面向對象的前提,其中方法在原地修改實例狀態,這顯然是副作用。

我正在研究的一個解決方案是使所有方法返回當前實例的克隆並進行適當的狀態修改。看起來很急切,但是當我決定讓代碼平行時可能會有所幫助,對吧?

混合這兩種範式的最佳實踐是什麼?餘額是多少?

謝謝。

+2

有趣和高度相關的閱讀:[是FP和OO正交嗎?](http://stackoverflow.com/q/3949618/395760) – delnan

+4

這是OO的前提嗎?那麼,爲什麼Effective Java建議使用不可變對象呢?我認爲你應該開始調和你的面向對象與專家實際上已經說過的觀點... –

回答

2

我覺得其實我再跟順便說一下你這個取景:

事實上,我對如何調解由一成不變的類型和純函數和隱含的無副作用的規則,不知道面向對象的前提,其中方法在原地修改實例狀態,這顯然是副作用。

我不會說對象字段的變化操作是OO的核心「前提」。根本不是(儘管相反,我認爲不變性是FP的核心前提)。對我而言,OO是一種思考程序模塊性比其他任何事情更好的方式。在我看來(也許是扭曲的)思維方式中,甚至哈斯克爾(Haskell) - 一種主張經常畏縮OO風格思維的語言 - 然而體現了一些面向對象的概念,因爲它有一個模塊系統,各種封裝實現的方式數據類型的細節等。另一方面,儘管它非常笨拙和加重,但我的Java代碼傾向於大量使用基本功能概念,如currying。

換句話說,我認爲這兩種方法在某種意義上是互補的。

現在,在一個不太理論和堅果和螺栓的水平......比方說,你有這樣的:

class Foo(val a : A, val b : B, val c : C) { 
    def setB(newb : B) : Foo = new Foo(a, newb, c) 
} 

...所以你可以說newFoo = foo.setB(b),你在原來的職位建議。我會說這是完全不錯的風格,並沒有引起關注(關於性能或可讀性或其他)。您將在Scala庫中看到很多這樣的不可變集合類。

+0

如果你說OO與Modularity相連,你可以描述它是如何實現的嗎? OO使用哪些功能來抑制模塊化? 我問,因爲我很好奇,我認爲很簡單,並實現模塊化我想不出有用的(獨家)面向對象的功能,實現這一點。也許多態主義'點菜'在這裏看到:http://www.infoq.com/presentations/Simple-Made-Easy? – AndreasScheinert

0

你可能想檢查Programming Scala的Functional Programming chapter(它是available free online)以獲得一些提示。

FP它不只是關於線程。高級功能可以幫助您清理和乾燥代碼,使其看起來更優雅。

+0

感謝您的回答。我完全相信FP的好處,並且已經應用​​了它們,但是我想知道在頂端文章中表達的二元性的前沿。 –

+0

FP不是關於'使你的代碼看起來優雅',它是關於通過可重用性的可組合性和模塊性。 – AndreasScheinert

+0

無論你說什麼 –

7

不可變類是橋接OO和FP的一種非常好的方法。 Scala的Collection Library是混合面向對象,不可變對象和函數式編程的絕佳例子。

在您自己的代碼中,Scala的case classes確實有助於實現不可變的對象,因爲它們有一個copy方法,可用作替換構建器模式。

// begin cheesy example 
case class Circle(center: (Double, Double), radius: Double) { 
    def move(c: (Double, Double)) = copy(center = c) 
    def resize(r: Double) = copy(radius = r) 
    def area = math.Pi * radius * radius 
} 

您可能也有利於豐富觀看希基的會談Persistent Data Structures and Managed ReferencesAre We There Yet?他們都非常出色地解釋了對不變性的需求,以及它如何幫助我們推理國家。他談論了關於Clojure的一切,但他的觀點同樣適用於Scala。

0

盡一切方法返回當前實例

的副本,如果你檢查的jQuery是怎麼做的,它採用了一種名爲方法鏈 每一個,否則將返回$此空返回法技術,所以你可以一直在調用方法。這就是爲什麼jQuery對象不會破壞JavaScript中的傳統程序用戶代碼。