顯示具有 java 標籤的文章。 顯示所有文章
顯示具有 java 標籤的文章。 顯示所有文章

2012年11月19日 星期一

Javascript is OOP?

這是個會引發"聖戰"之類的話題,我想這件事情留給有能力的人去回答,退而在此討論javascript"做得到"跟"做不到"的事情

is-a關係,很多人第一刻在繼承裡面學到的。我們說objC is a objP,也就是說可以把objC當成objP一樣對待,兒子應該跟老爸有相同的四肢構造。

可以先看底下的文章,解釋如何使用javascript的prototype完成繼承
http://peter.michaux.ca/articles/transitioning-from-java-classes-to-javascript-prototypes

首先要解釋的是javascript是duck type的程式語言,很多程式語言都是duck type,也就是一個物件看起來像是鴨子(特徵attributes),走路像鴨子(methods),那麼我們就認定他是一隻鴨子

javascript藉由prototype,隨時隨地可以將一個物件的屬性跟介面加入另外一個物件裡面,讓一個物件看起來像是另外一類的物件,比方說在上面peter給的範例實作了observer pattern,如果今天我有個物件擁有update方法,那我就看起來像是observer,真的是這樣嗎?所以要預防這種事情,絕對的方式是用instanceof來檢驗update方法真的來自observer。第二個問題,跟著如果併入另外一組物件的屬性跟介面(也有update)的時候,兩個function A跟B想要的是不同型態的參數,這時候呼叫的是哪一個update??似乎兩者都可以互通,這是duck type的特性
extends(WeatherModel, Observable);
extends(WeatherModel, Observable2);<=????????????????
function A(o:Observable);<=????????????????
function B(o:Observable2);<=????????????????
可以預期的是上面的程式碼可以順利運作(一定會呼叫某個物件的update,或者某個型態的update),但是未必如你所料

回頭來看java/C++,如果今天要在程式執行期間的實作一組介面,恐怕沒有辦法,你只能期待能不能從java Reflection或者C++的pointer跟強制轉型,擠出一點希望,但反過來說,是你可以確定的是不會讓一個不該屬於某個介面的物件放進一個不應該屬於那個型態的function之內(compile time)

OO上很重的一個觀念是is-a的體現,但兩者不同的做法沒有絕對的好壞,因為OO上is-a的解釋很寬廣。從上面可以看出來java/C++是strong type,所以在這種事情上給了某種保證,但是也失去了彈性,javascript獲取了彈性(duck type),但是也付出了某種代價。
OO的體現差異,上面提到的只是兩者之間在OO方面實作差異的冰山一角,希望能對大家在OO上面有進一步的體驗。

Peter的文章告訴我們不要從語言上面學習OO是個很重要的觀念,同時了解語言的差異在體現OO的特性上也很有幫助。對於學習OO觀念,或許從CRC卡上著手是個不錯的開始

可是也別太過極端,認為任何程式語言都可以實作OO,那恐怕是程度上的區別。不要被程式語言綁架了體現OO的作法,但一個程式語言號稱是OOP亦有他的道理

P.S. 網路上爬了一堆號稱javascript繼承實作的方式(甚至多重繼承),請仔細檢驗,是否能夠達成呼叫super class的constructor?是否能使用super class的variable?這往往跟我們直覺不大一樣,一旦在sub class/instance 呼叫了super class的method,其中帶有super class的variable,很快地會看到interpreter跟你抱怨,那個method不是一個function(奇怪吧!)
比方說下面這個網址的實作,至少就犯了兩三個錯誤
www.amirharel.com/2010/06/11/implementing-multiple-inheritance-in-javascript/

下面是一個例子,討論串中有它的問題
http://www.steinbit.org/words/programming/multiple-inheritance-in-javascript

2012年7月18日 星期三

Android之JNI

就如我第一篇android說的,我不是很關心android如何應用這樣的機制去寫作應用程式,但是本身卻對機制的原理相當感興趣,如果想要學會如何使用NDK做JNI可以參考參考資料,步驟大概如這張圖

針對JNI在Android上大概分成三層Java/App<=>JNI Lyaer<=>Native
因為有些動作只能在Native完成,所以不得不使用C語言,但是使用者介面又是以Java構成,要使兩者可以溝通就是透過JNI的機制
首先看Java code,必須使用System.loadLibrary載入相對應的share object(.so),對於native function則使用native關鍵字標示出來
 在java內已經宣告了java這邊的介面,用native表明到時候要透過JNI去呼叫Native程式,這時候用javah來編譯出C++ header file,使用JDK工具以特定格式去產生Native function的介面,這樣JNI才會認得兩邊的接口/介面,JNI這位中間人,就是依賴這樣的規則才能為兩邊牽線,下面是javah產生出來的.h檔案
跟著就是自行產生.cpp檔案,實作.h的介面

當呼叫System.loadLibrary的時候JNI會呼叫JNI_OnLoad函數,並且剖析share object(JNIEXPORT關鍵字做的手腳,export某些symbol),並且動態的將這些method註冊到JNI中,java code呼叫某個native method的時候其實是去尋找JNI中註冊表的method,來做呼叫

由於兩種程式語言的基本type並不相同,在兩者之間傳遞資料變成一件很重要的事情,所以如何對應呢?
<type>=>j<type>,如boolean(java)=>jboolean(c++),支援的type有boolean、byte、char、short、int、long、float、double

那麼如何在Native裡面呼叫java的某個物件的某個方法呢?其實如果熟悉Java Reflection這問題會容易解的多。
JNIEnv包含了JNI_OnLoad的時候做的資訊以及JVM的資訊,透過JNIEnv可以找到對應的class,再透過對應的class找出method與field,建構適當的signature就可執行某個object的method,跟Reflection的工作是大同小異的。


另外有個地方要注意的是,預設的狀況在Native並不會增加reference count,也就是說如果再Native functionm用static variable參考到某個object,並不表示下次來,這個object還會存在。可以使用env->NewGlobalRef(some_java_object)來取得global reference,但是要注意,這個global reference會使得garbage collect無法回收該物件,需要使用env->DeleteGlobalRef(some_java_object)來歸還


Native的exception是由JNI回報的,但是C++的異常蠻明顯不大相容於java,且處理很容易讓程式當掉,這時候JNIEnv可能用ExceptionOccured、ExceptionClear、ThrowNew報告異常

參考文件:
http://cheng-min-i-taiwan.blogspot.tw/2011/05/java-native-interface-jni-androidndk.html
http://blog.csdn.net/nicholas6lee/article/details/7324087
http://gyht0808.iteye.com/blog/763435
http://my.unix-center.net/~Simon_fu/?p=833

2012年3月3日 星期六

[舊聞]Java 6上的swing framework擴展

http://java.sun.com/developer/technicalArticles/javase/swingappfr/#actions
有人問到我一些關於annotation的東西,讓我想到這個,已經有三四年沒看到了,竟然依時間找不到,找到就隨手做個筆記