發表文章

目前顯示的是 9月, 2020的文章

factory模式 (建構子)

這其實應該算是「 constructor 」的衍伸。 因為factory模組要的就是如何產生物件實體。 如以下範例(取自「 壞蛋的密室 」): class Symbol { final String name; static Map<String, Symbol> _cache; factory Symbol(String name) { if (_cache == null) { _cache = {}; } if (_cache.containsKey(name)) { return _cache[name]; } else { final symbol = new Symbol._internal(name); _cache[name] = symbol; return symbol; } } Symbol._internal(this.name); } 使用方式如下: var a = new Symbol('something'); var b = new Symbol('something'); assert(identical(a, b)); // true! 常識來說,constructor自預設「return 實體」做結尾,但Dart/Flutter的factory模組可以加在constructor中。 在constructor前面加上「factory」,同時必須要用「return返回實體」做constructor的結尾。 這樣的做法雖然在使用上很方便(不用再寫Factory模式),但在邏輯上和物件導向使用上,可能會帶來很嚴重的混亂。 最明顯的問題是:Factory模式並不預設return用來實作Factory的物件自己,總是會return一系列擴充了A介面或物件的A1/A2/A3/A4...。 如果物件自己就是Factory模式,那請問要怎麼返回子類別呢? 這問題很奇妙。 因為這問題顯示了物件導向編譯程式並沒有想像中的符合人類的直覺或思考模式。 試想像一下:物件A在編譯的時候,要如何知道自己的子類別存在呢? 但事實是:這樣的程式技巧確實存在。也就是說「編譯器能否編譯這樣的物件」決定...

List的使用

Dart沒有像Java那樣的標準陣列型態資料可以使用...... 但是它有List這個物件類別,用法跟Java的List很像。 有add、有remove、甚至還有asMap(用index直接做成索引Key)。 但是Dart的List在使用上確實比較像陣列,而不是物件(不需要「宣告」)。 要設置一個List參數,只需要使用中引號「 [ ] 」即可。如果要「限定」它的長度,就在前面加上「const」。 void main() { List < dynamic > a = const [ 1 , '123' , true ]; print (a[ 1 ]); // Output:123 a.add( 123 ); // error } 另外, List的迭代循環方式跟Java也不同。 Java中,只要使用for(...)就可以自動取得迭代循環,但在Dart,必須要使用forEach(...)。 main () { List < String > list = new List < String > (); list. add ( 'one' ); list. add ( 'two' ); list. add ( 'twelve' ); list. forEach ((element) => print (element)); Set < String > set = Set . from (list); set . forEach ((element) => print (element)); } 它是種lambda函數式,必須要傳入一個匿名函數(概念類似匿名物件),然後裡面接收一個傳入參數來接收每一輪迭代循環取得的資料。

物件的MIXIN機制和它的使用限制

【Java的Interface只能定義接口名稱,無法定義它的內容,而且擴充了接口等於要負責提供實作內容。MIXIN機制提供了類似Interface的機制,但可以直接定義內容。】 (本文為 iT邦的文章 閱讀後想法,原文作者似乎不熟悉Java。) (另外參考了 簡書上的文章 。) mixin似乎是種特殊物件類別的宣告方式,一個物件可以「擴充」多個MIXIN物件。 mixin物件本身沒辦法(也不需要)宣告建構子。 使用方式(擴充mixin物件)為「with MIXIN物件名稱」 mixin Android { String android() => "I'm android developer." ; } mixin IOS { String ios() => "I'm ios developer." ; } class Language { String name; int ver; Language( this .name, this .ver); String introduce() => "I'm $name . Nice to meet you." ; } class Flutter extends Language with Android , IOS { Flutter( String name, int ver): super (name, ver); } void main() { var coder = new Flutter( 'Tracy' , 23 ); print (coder.introduce()); print (coder.android()); print (coder.ios()); } 下面這個範例可以看到... 1.mixin物件可以設置參數。 2.mixin的函數可以不提供實作內容。(類似abstract。) mixin DrawFunc { String content = '..' ; String what ( ) ; ...

接著來擴充一個物件

D art跟Java一樣只能繼承一個父類,。 class Demo { String name; int type; Demo( this .name, this .type); String introduce() => "This class is $name ." ; } class Demo2 extends Demo { Demo( String name, int type): super (name, type); } void main() { var F = new Demo2( 'for demo' , 5 ); print (F.introduce()); } 可以看到擴充建構子的方式是使用「:super(.....)」。 但怎麼擴衝或複寫建構子內容?這樣做明顯只是完整使用父類別的建構子而已。而且還有多重建構子的部分又要怎麼使用? (會有這些疑問,因為本文是基於這份 iT邦的網路教學 的閱讀後心得寫成。) 原來只要在「super(...)」後繼續加上引號繼續編寫內容即可。例如下面這段... DemoX() :super() { ... } (但這是否又表示「super()」並非必須的?) 另外比較特殊的是lambda演算法式宣告的函數「introduce()」,函數前面有宣告回傳資料型態,但後方的程式碼整個直接省略return。 (這是lamdba演算法的標準寫法嗎?暫時沒有找到明確答案,但似乎是如此。)

從宣告一個Class開始

 因為之前是學Java,所以習慣物件導向,自然習慣了「寫程式,從怎麼寫物件開始。」 void main(){ var D = new Demo( 'Dart Tutorial' , 'Happy coding' , '2019/9/14' ); print (D.title); } class Demo { String title; //標題 String description; //資訊 String publishTime; //時間 Demo( String title, String description, String publishTime ) { this .title = title; this .description = description; this .publishTime = publishTime; } } 以上可以看到一個標準物件的結構。 一個物件只能有一個建構子。這是比較奇妙的地方。 void main() { var d1 = new Demo( 'Dart Tutorial' , 'Happy coding' , '2019/9/14 ); print (d1.title); //Output: Dart Tutorial var d2 = new Demo.only Description ( "Happy coding Only Description" ); print (d2.url); //Output: https://123.456 var d3 = new Demo.onlyTitle( "Dart Tutorial Only title" ); print (d3.title); //Output: Only title } class Demo { String _title; //標題 增加下引線表示這是private String _descripti...