2014-01-24 45 views
1

Java和Javascript都允許執行靜態代碼的不同方式。 Java允許您在類的主體中擁有靜態代碼,而JS允許您在類定義之外執行靜態代碼。例子:是否有可能使用Dart執行靜態代碼?

的Java:

public class MyClass { 
    private static Map<String,String> someMap = new HashMap<String,String(); 
    static { 
     someMap.put("key1","value"); 
     someMap.put("key2","value"); 
     SomeOtherClass.someOtherStaticMethod(); 
     System.out.println(someMap); 
    } 
} 

JS(基本上是一類以外的任何JS代碼):

var myint = 5; 
callSomeMethod(); 
$(document).ready(function() { 
    $("#hiddenelement").hide(); 
}); 

但是,它似乎像飛鏢既支持的兩種方式。聲明全局變量和方法是受支持的,但調用方法和執行代碼就像在JS中不是。這隻能在main()方法中完成。此外,類中的靜態代碼也是不允許的。

我知道Dart有其他的方法可以像我的第一個例子那樣靜態填充一個Map,但是還有另外一個我能想到的需要這個的例子。

讓我們考慮以下CarRegistry實現,它允許您將汽車模型的字符串映射到相應類的實例。 F.E.當你從JSON數據車模:

class CarRegistry { 
    static Map<String, Function> _factoryMethods = new HashMap<String, Function>(); 

    static void registerFactory(String key, Car factory()) { 
     _factoryMethods[key] = factory; 
    } 

    static Car createInstance(String key) { 
     Function factory = _factoryMethods[key]; 
     if(factory != null) { 
      return factory(); 
     } 
     throw new Exception("Key not found: $key"); 
    } 
} 

class TeslaModelS extends Car { 

} 

class TeslaModelX extends Car { 

} 

爲了能夠調用CarRegistry.createInstance("teslamodelx");,該類必須先進行登記。在Java中,可以通過將以下行添加到每個Car類:static { CarRegistry.registerFactory("teslamodelx" ,() => new TeslaModelX()); }來完成。你不想要的是將所有汽車硬編碼到註冊表中,因爲它將失去它作爲註冊表的功能,並且增加了耦合性。您希望能夠通過只添加一個新文件來添加新車。在JS中,您可以在類構造外調用CarRegistry.registerFactory("teslamodelx" ,() => new TeslaModelX());行。

飛鏢怎麼能做出類似的事情?

即使您允許編輯多個文件來添加一輛新車,如果您正在編寫一個沒有main()方法的庫,也是不可能的。那麼唯一的選擇就是在第一次調用Registry.createInstance()方法時填寫地圖,但它不再是註冊表,那麼只是包含硬編碼汽車列表的類。

編輯:一個小除了最後一條語句我在這裏提出:填充這種登記在createInstance()方法僅僅是一種選擇,如果註冊表在我自己的圖書館居住。如果,f.e.我想將我自己的類註冊到由我導入的不同庫提供的註冊表中,這不再是一種選擇。

回答

2

爲什麼所有關於靜態的大驚小怪? 您可以創建一個getter來檢查初始化是否已完成(_factoryMethods != null),如果不是,則返回映射。

據我瞭解,這是所有關於這個代碼應該在什麼時候執行。

我上面顯示的方法是延遲初始化。
我認爲這通常是我猜測的首選方式。
如果您希望在庫加載
我不知道其他的方式調用庫從main()init()方法,並添加初始化代碼此庫init()方法做初始化。

這裏有一個關於這個話題executing code at library initialization time

+2

就像dart-misc組提到的人一樣,我更喜歡我的庫不需要用戶調用初始化方法就可以使用。懶惰初始化方法可能在這個例子中工作,但是當我試圖將自己的類註冊到另一個庫提供的註冊表中時,這是不可能的。 –

+1

據我所知不。 –

1

我試圖駕駛一個同樣主題庫時遇到了同樣的問題的討論。使用dart:mirrors遍歷類在庫中,並確定它們是否是通過這樣的註釋標記

我的初步嘗試探索(使用自己的代碼作爲例子的一部分):

@car('telsamodelx') 
class TelsaModelX extends Car { 
} 

如果是這樣,他們會自動填充到註冊表中。然而,表現並不是很好,我不確定它會如何擴展。

最後我採取了更麻煩的辦法:

// Inside of CarRegistry.dart 
class CarRegister { 
    static bool _registeredAll = false; 
    static Car create() { 
    if (!_registeredAll) { _registerAll()); } 
    /* ... */ 
    } 
} 

// Inside of the same library, telsa_model_x.dart 
class TelsaModelX extends Car {} 

// Inside of the same library, global namespace: 
// This method registers all "default" vehicles in the vehicle registery. 
_registerAll() { 
    register('telsamodelx',() => new TelsaModelX()); 
} 

// Inside of the same library, global namespace: 
register(carName, carFxn) { /* ... */ } 

庫之外,消費者只好打電話register();地方登記他們的車輛。

這是不必要的重複,不幸的是分離的方式,使得它難以跟蹤類中的登記,但它無論是繁瑣的代碼或通過使用dart:mirrors.

YMMV命中性能,但由於數可註冊的項目不斷增加,我開始重新考慮dart:mirrors的方法。

+0

你可以鏈接到你尋找註釋類的代碼嗎? –

+1

我正在瀏覽我的源代碼,它不在那裏 - 我想我可能已經放棄了代碼分支而沒有先推到任何地方。懸崖筆記的版本是:使用'dart:mirrors'中的'currentMirrorSystem'來遍歷每個'LibraryMirror',並且在每個LibraryMirror中迭代每個類,查看'metadata'內部的'ClassMirror'對象以匹配您的註釋。 – ALW

相關問題