<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8077026500811766047</id><updated>2024-09-05T05:13:12.280+08:00</updated><category term="Dart"/><category term="dartlang"/><category term="Bug"/><category term="CSS"/><category term="CSS3"/><category term="Cascading"/><category term="Chrome"/><category term="Curry-Function"/><category term="Design-Pattern"/><category term="Functional-Programming"/><category term="HTML"/><category term="Immutable"/><category term="Programming"/><category term="Proxy-Object"/><category term="Safari"/><title type='text'>Ticore Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://ticore.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8077026500811766047/posts/default'/><link rel='alternate' type='text/html' href='http://ticore.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>{id: &quot;Ticore&quot;}; //</name><uri>http://www.blogger.com/profile/01433005931305983346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJGv_kYSLadwfTxjI8BM7VyscM7QTQciGFJ_lUo89zzSgPEXwK13K-LX7j8zHgjzZZPz6Tfr5hySpNaEDAn5tpZLhXPaKrUTYXqIZzpH-gYRFOBUFKMcnLqMYn6ROlN78/s220/OrigamiMurex.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>4</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8077026500811766047.post-8692525545877974697</id><published>2015-05-11T18:23:00.002+08:00</published><updated>2015-05-12T12:54:23.255+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Dart"/><category scheme="http://www.blogger.com/atom/ns#" term="dartlang"/><category scheme="http://www.blogger.com/atom/ns#" term="Immutable"/><title type='text'>Dart 常數 Immutable 物件上附加 Mutable 成員</title><content type='html'>&lt;p&gt;
承前一篇 Dart 類別只要一用到常數建構子，所有的成員欄位都必須要 const&lt;br/&gt;
就算成員是 Map or List 內部資料也全部都要 const (transitively immutable)&lt;br/&gt;
萬一之後突然需要 mutable member 會變得很麻煩
&lt;/p&gt;
&lt;span class=&quot;fullpost&quot;&gt;
&lt;p&gt;
我測試了許多寫法都很難跳脫 const&lt;br/&gt;
後來想到一種方式將常數物件自身當作 key，配合利用另一個 model 容器存取資料
&lt;/p&gt;
&lt;pre&gt;
/*
 * 在常數 Immutable 物件上附加 Mutable 成員
 */

class Model {
  static final map = new Map();
  static get(obj) =&amp;gt; map.putIfAbsent(obj, () =&amp;gt; {});
}


class ImmutableObj {
  final int i;
  const ImmutableObj(this.i);
  
  String get name =&amp;gt; Model.get(this)[&#39;name&#39;];
  set name(value) =&amp;gt; Model.get(this)[&#39;name&#39;] = value;
}


void main() {
  var c1 = const ImmutableObj(1);
  c1.name = &quot;Const Obj 1&quot;;
  print(c1.name); // Const Obj 1
  
  var c2 = const ImmutableObj(2);
  func(); // null
  c2.name = &quot;Const Obj 2&quot;;
  func(); // Const Obj 2
}

void func() {
  print(const ImmutableObj(2).name);
}
&lt;/pre&gt;
&lt;p&gt;
本來想再進一步將 Mutable Part 寫成 Mixin&lt;br/&gt;
結果執行過不了~~ 只能等看看之後會不會修改&lt;br/&gt;
&lt;a href=&quot;https://code.google.com/p/dart/issues/detail?id=9745&quot;&gt;Issue 9745: Make mixins forward const constructors.&lt;/a&gt;
&lt;/p&gt;


&lt;p&gt;
Simon 介紹也可以用 &lt;a href=&quot;http://stackoverflow.com/questions/13358018/what-is-the-dart-expando-feature-about-what-does-it-do&quot;&gt;Expando &lt;/a&gt;來做
&lt;p/&gt;

&lt;pre&gt;
class ImmutableObj {
  final int i;
  const ImmutableObj(this.i);
}


class ExpObj {
  static Expando&lt;ExpObj&gt; exp = new Expando&lt;ExpObj&gt;(&quot;ExpObj&quot;);
  
  factory ExpObj(obj) {
    if (exp[obj] == null) {
      exp[obj] = new ExpObj._();
    }
    return exp[obj];
  }
  
  ExpObj._();
  String name;
}



void main() {
  var c1 = const ImmutableObj(1);
  new ExpObj(c1).name = &quot;Const Obj 1&quot;;
  print(new ExpObj(c1).name); // Const Obj 1
  
  var c2 = const ImmutableObj(2);
  func(); // null
  new ExpObj(c2).name = &quot;Const Obj 2&quot;;
  func(); // Const Obj 2
}

void func() {
  print(new ExpObj(const ImmutableObj(2)).name);
}
&lt;/pre&gt;

&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;

&lt;p&gt;
2013/12/26&lt;br/&gt;
又想到可以將外部 Mutable Model 合併為單一 Class 的寫法
&lt;/p&gt;
&lt;pre&gt;
/*
 * 在常數 Immutable 物件上附加 Mutable 成員
 */

class ImmutableCls {
  
  // immutable part
  final i;
  const ImmutableCls(this.i);
  
  // mutable part
  static final _map_ = {};
  get mutable =&amp;gt; _map_.putIfAbsent(this, () =&amp;gt; {});
  get name =&amp;gt; mutable[&quot;name&quot;];
  set name (value) =&amp;gt; mutable[&quot;name&quot;] = value;
  
}



void main () {
  
  print(const ImmutableCls(1) == const ImmutableCls(1));
  print(const ImmutableCls(1).name); // null
  const ImmutableCls(1).name = &quot;Const Obj 1&quot;;
  print(const ImmutableCls(1).name); // Const Obj 1
  
}
&lt;/pre&gt;
&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://ticore.blogspot.com/feeds/8692525545877974697/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://ticore.blogspot.com/2015/05/dart-immutable-mutable.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8077026500811766047/posts/default/8692525545877974697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8077026500811766047/posts/default/8692525545877974697'/><link rel='alternate' type='text/html' href='http://ticore.blogspot.com/2015/05/dart-immutable-mutable.html' title='Dart 常數 Immutable 物件上附加 Mutable 成員'/><author><name>{id: &quot;Ticore&quot;}; //</name><uri>http://www.blogger.com/profile/01433005931305983346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJGv_kYSLadwfTxjI8BM7VyscM7QTQciGFJ_lUo89zzSgPEXwK13K-LX7j8zHgjzZZPz6Tfr5hySpNaEDAn5tpZLhXPaKrUTYXqIZzpH-gYRFOBUFKMcnLqMYn6ROlN78/s220/OrigamiMurex.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8077026500811766047.post-1695475484850858877</id><published>2014-02-07T00:00:00.000+08:00</published><updated>2015-05-12T12:54:23.247+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Dart"/><category scheme="http://www.blogger.com/atom/ns#" term="dartlang"/><category scheme="http://www.blogger.com/atom/ns#" term="Design-Pattern"/><category scheme="http://www.blogger.com/atom/ns#" term="Programming"/><category scheme="http://www.blogger.com/atom/ns#" term="Proxy-Object"/><title type='text'>Dart 數種語法特色組成完美 Proxy</title><content type='html'>
&lt;p&gt;
在 &lt;a href=&quot;http://www.infoq.com/presentations/dart-motivation-future&quot;&gt;Civilizing Web Programming with Dart&lt;/a&gt;&lt;br/&gt;
看到 Dart 實作的代理物件 Proxy 方式&lt;br/&gt;
僅僅只需要少量的程式碼&lt;br/&gt;
就能夠很容易地做出自己的 Proxy&lt;br/&gt;
完全不需要繼承任何特殊的類別&lt;br/&gt;
這真的非常神奇~!
&lt;/p&gt;
&lt;span class=&quot;fullpost&quot;&gt;
&lt;p&gt;
甚至能夠 Mimic 對象物件介面通過型別檢查&lt;br/&gt;
代理對象程式碼提示&lt;br/&gt;
與其它原始物件做二元運算子混和操作&lt;br/&gt;
仔細研究之後，發現它包含了許多原本已知 Dart 語法特色
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;mirror&lt;/b&gt;&lt;br/&gt;
即是反射 reflection 功能，Dart 提供了多種反射方式&lt;br/&gt;
InstanceMirror, TypeMirror, MethodMirror... 等&lt;br/&gt;
在這裡用到 InstanceMirror 配合 noSuchMethod Invocation&lt;br/&gt;
委任呼叫到反射對象上
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;noSuchMethod&lt;/b&gt;&lt;br/&gt;
只要物件宣告 noSuchMethod，任何對物件存取呼叫未宣告的動作&lt;br/&gt;
都會被轉向到此方法，得到一個 Invocation 物件&lt;br/&gt;
能知道呼叫對象名稱、參數等各種資訊&lt;br/&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;class as interface&lt;/b&gt;&lt;br/&gt;
類別即是介面，這乍看之下有點雞肋的特色&lt;br/&gt;
其實非常有用，除了 Mock Class 之外&lt;br/&gt;
在 Proxy 功能上也提供了很大幫助&lt;br/&gt;
因為通常要代理的對象物件不見得會有抽離介面&lt;br/&gt;
但是在 Dart 類別即是介面&lt;br/&gt;
Proxy 類別可以很容易實作代理對象介面&lt;br/&gt;
通過需要型別檢查的地方
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;overloading operator&lt;/b&gt;&lt;br/&gt;
Dart 是少數提供過載運算子的動態語言&lt;br/&gt;
在這個強大語法特色加持下&lt;br/&gt;
許多運算子呼叫都能被當作函式一樣被委任&lt;br/&gt;
Proxy 也能代理運算子動作
&lt;/p&gt;
&lt;p&gt;
&lt;b&gt;annotation&lt;/b&gt;&lt;br/&gt;
類似 Metadata&lt;br/&gt;
Dart 額外提供了一個 proxy object&lt;br/&gt;
只要類別標註 @proxy annotation&lt;br/&gt;
語法分析器就會知道該類別是一個 Proxy&lt;br/&gt;
進而忽略相關未宣告方法的錯誤
&lt;/p&gt;
&lt;p&gt;
以下是 Dart Proxy 例子：
&lt;/p&gt;
&lt;pre&gt;import &quot;dart:mirrors&quot;;

// 作為被代理的對象類別
class Point {
  int x, y;
  Point(this.x, this.y);
  Point operator +(a) =&gt; new Point(x + a.x, y + a.y);
  Point operator -(a) =&gt; new Point(x - a.x, y - a.y);
  toString() =&gt; &quot;Point($x , $y)&quot;;
}


// 尚未實作代理對象介面的 Proxy
// @proxy 表示是 Proxy 物件，進行介面沒有的操作不會產生警告
@proxy
class Proxy {
  InstanceMirror targetMirror;
  Proxy(target) : targetMirror = reflect(target);
  noSuchMethod(Invocation inv) =&gt; targetMirror.delegate(inv);
  toString() =&gt; targetMirror.reflectee.toString();
}


// 已經實作代理對象介面的 Proxy，能通過型別檢查
class PointProxy extends Proxy implements Point {
  PointProxy(target) : super(target);
  
  // noSuchMethod 表示已經隱含實作一切介面所需東西，不會產生未實作警告
  noSuchMethod(Invocation inv) =&gt; super.noSuchMethod(inv);
}


void main() {

  print(new Proxy(new Point(0, 0))); // Point(0 , 0)
  print(new Proxy(new Point(2, 0)) + new Point(0, 1)); // Point(2 , 1)
  Point p1 = new PointProxy(new Point(2, 0));
  print(p1 + new Point(0, 1));  // Point(2 , 1)
  
}
&lt;/pre&gt;
&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://ticore.blogspot.com/feeds/1695475484850858877/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://ticore.blogspot.com/2014/02/perfect-proxy-by-dartlang-flavors.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8077026500811766047/posts/default/1695475484850858877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8077026500811766047/posts/default/1695475484850858877'/><link rel='alternate' type='text/html' href='http://ticore.blogspot.com/2014/02/perfect-proxy-by-dartlang-flavors.html' title='Dart 數種語法特色組成完美 Proxy'/><author><name>{id: &quot;Ticore&quot;}; //</name><uri>http://www.blogger.com/profile/01433005931305983346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJGv_kYSLadwfTxjI8BM7VyscM7QTQciGFJ_lUo89zzSgPEXwK13K-LX7j8zHgjzZZPz6Tfr5hySpNaEDAn5tpZLhXPaKrUTYXqIZzpH-gYRFOBUFKMcnLqMYn6ROlN78/s220/OrigamiMurex.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8077026500811766047.post-2945411464318599518</id><published>2013-02-05T00:00:00.000+08:00</published><updated>2015-05-12T12:58:26.413+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Cascading"/><category scheme="http://www.blogger.com/atom/ns#" term="Curry-Function"/><category scheme="http://www.blogger.com/atom/ns#" term="Dart"/><category scheme="http://www.blogger.com/atom/ns#" term="dartlang"/><category scheme="http://www.blogger.com/atom/ns#" term="Functional-Programming"/><title type='text'>神奇的一行 Dart 程式</title><content type='html'>&lt;p&gt;
在看 Google Dart 語言時候&lt;br/&gt;
把兩個很有特色的功能接合起來&lt;br/&gt;
結果得到以下神奇的一行程式碼
&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;pre&gt;
class FunCls {
  num i , j , k;
  num call () =&gt; i + j + k;
}

void main() {
  // 神奇的一行
  print((new FunCls() ..i = 1 ..j = 2 ..k = 3)()); // 6
}
&lt;/pre&gt;
&lt;p&gt;
僅僅只用了一行，就完成物件初始化，連續指定三個屬性，最後再 call function 加總&lt;br/&gt;
以上主要是來自 Dart 兩個 Feature
&lt;/p&gt;
&lt;p&gt;
&lt;a href=&quot;http://www.dartlang.org/articles/emulating-functions/&quot;&gt;Emulating Functions&lt;/a&gt; 
與 
&lt;a href=&quot;http://news.dartlang.org/2012/02/method-cascades-in-dart-posted-by-gilad.html&quot;&gt;Cascade Operator&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
Cascade Operator 很像是 jQuery API 與 Curry Function&lt;br/&gt;
但是 Dart Cascade 對象是物件實體，配合模擬 Function 功能達到類似的效果&lt;br/&gt;
而且 Dart 是從語法上支援這項功能，不需要特別實作&lt;br/&gt;
就能夠動態決定是要返回物件 (兩個點) 還是要返回回傳值 (一個點)
&lt;/p&gt;
</content><link rel='replies' type='application/atom+xml' href='http://ticore.blogspot.com/feeds/2945411464318599518/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://ticore.blogspot.com/2013/02/one-line-dart-lang.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8077026500811766047/posts/default/2945411464318599518'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8077026500811766047/posts/default/2945411464318599518'/><link rel='alternate' type='text/html' href='http://ticore.blogspot.com/2013/02/one-line-dart-lang.html' title='神奇的一行 Dart 程式'/><author><name>{id: &quot;Ticore&quot;}; //</name><uri>http://www.blogger.com/profile/01433005931305983346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJGv_kYSLadwfTxjI8BM7VyscM7QTQciGFJ_lUo89zzSgPEXwK13K-LX7j8zHgjzZZPz6Tfr5hySpNaEDAn5tpZLhXPaKrUTYXqIZzpH-gYRFOBUFKMcnLqMYn6ROlN78/s220/OrigamiMurex.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8077026500811766047.post-2453815781211416992</id><published>2010-04-05T20:44:00.000+08:00</published><updated>2015-05-12T12:54:49.631+08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Bug"/><category scheme="http://www.blogger.com/atom/ns#" term="Chrome"/><category scheme="http://www.blogger.com/atom/ns#" term="CSS"/><category scheme="http://www.blogger.com/atom/ns#" term="CSS3"/><category scheme="http://www.blogger.com/atom/ns#" term="HTML"/><category scheme="http://www.blogger.com/atom/ns#" term="Safari"/><title type='text'>WebKit, Prestro CSS3 Transform &amp; ScrollBar Rendering Bug</title><content type='html'>&lt;p&gt;
又發現一個 CSS3 渲染的 Bug&lt;br/&gt;
主要發生在所有 WebKit, Prestro 為基礎的瀏覽器上 Chrome、Safari、Opera
而 Gecko - Firefox 則是正常的&lt;br/&gt;
對含有捲軸的元素設定 CSS3 transform rotate 時&lt;br/&gt;
將會造成捲軸消失不見
&lt;/p&gt;

&lt;p&gt;
WebKit, Prestro CSS3 Transform &amp; ScrollBar Rendering Bug Demo Code：
&lt;/p&gt;

&lt;pre&gt;
&amp;lt;style type=&quot;text/css&quot;&amp;gt;

.transformBug {
  border: 1px solid;
  background-color: #DDF;
  overflow: scroll;
  -webkit-transform: rotate(2deg);
  -moz-transform: rotate(2deg);
  -o-transform: rotate(2deg);
  width: 100px;
  height: 100px;
  margin: 10px;
}

&amp;lt;/style&amp;gt;

&amp;lt;div class=&quot;transformBug&quot;&amp;gt;
WebKit CSS3 Transform &amp;amp; ScrollBar Rendering Bug
&amp;lt;/div&amp;gt;

&lt;/pre&gt;

&lt;p&gt;
WebKit, Prestro CSS3 Transform &amp; ScrollBar Rendering Bug Demo
&lt;/p&gt;

&lt;hr /&gt;

&lt;style type=&quot;text/css&quot;&gt;

.transformBug {
  border: 1px solid;
  background-color: #DDF;
  overflow: scroll;
  -webkit-transform: rotate(2deg);
  -moz-transform: rotate(2deg);
  -o-transform: rotate(2deg);
  width: 100px;
  height: 100px;
  margin: 10px;
}

&lt;/style&gt;

&lt;div class=&quot;transformBug&quot;&gt;
WebKit, Prestro CSS3 Transform &amp;amp; ScrollBar Rendering Bug
&lt;/div&gt;

&lt;hr /&gt;

&lt;p&gt;
以上的 Bug 至少會發生在以下的瀏覽器上&lt;br/&gt;
Google Chrome 4.1.249.1045 win&lt;br/&gt;
Opeara 10.51 win&lt;br/&gt;
Safari 4.0.4 win
&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://ticore.blogspot.com/feeds/2453815781211416992/comments/default' title='張貼留言'/><link rel='replies' type='text/html' href='http://ticore.blogspot.com/2010/04/chrome-css3-transform-scrollbar.html#comment-form' title='0 個意見'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8077026500811766047/posts/default/2453815781211416992'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8077026500811766047/posts/default/2453815781211416992'/><link rel='alternate' type='text/html' href='http://ticore.blogspot.com/2010/04/chrome-css3-transform-scrollbar.html' title='WebKit, Prestro CSS3 Transform &amp; ScrollBar Rendering Bug'/><author><name>{id: &quot;Ticore&quot;}; //</name><uri>http://www.blogger.com/profile/01433005931305983346</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJGv_kYSLadwfTxjI8BM7VyscM7QTQciGFJ_lUo89zzSgPEXwK13K-LX7j8zHgjzZZPz6Tfr5hySpNaEDAn5tpZLhXPaKrUTYXqIZzpH-gYRFOBUFKMcnLqMYn6ROlN78/s220/OrigamiMurex.jpg'/></author><thr:total>0</thr:total></entry></feed>