在很多語言中,如果你嘗試實例化抽象類,你會得到編譯時錯誤。 但是,在Dart中,編譯時會出現警告,運行時異常AbstractClassInstantiationError
。爲什麼抽象類實例化不是飛鏢運行時錯誤?
這是爲什麼?有人可以提供一個例子,在哪裏編譯這樣的代碼是合理的?
在很多語言中,如果你嘗試實例化抽象類,你會得到編譯時錯誤。 但是,在Dart中,編譯時會出現警告,運行時異常AbstractClassInstantiationError
。爲什麼抽象類實例化不是飛鏢運行時錯誤?
這是爲什麼?有人可以提供一個例子,在哪裏編譯這樣的代碼是合理的?
Dart試圖讓您在開發程序時運行它。 這就是爲什麼在其他語言中編譯時錯誤的很多事情都是Dart中的編譯時警告和運行時錯誤。這包括「x是Foo」,其中Foo不存在,使用不存在的類型進行類型註釋,以及調用部分(抽象)類的構造函數。
簡而言之:因爲它不是一個阻止程序被編譯的問題(不像語法錯誤可能意味着文件的其餘部分被錯誤地解釋),所以沒有理由阻止你運行代碼。只有當你打到實際依賴於問題的分支時,你的程序纔會停止。
看來,答案是抽象類factory constructor:
abstract class Foo {
factory Foo() { // make Foo appear to be instantiable
return new Bar();
}
some(); // some abstract method
Foo.name() {} just a named constructor
}
class Bar extends Foo {
Bar():super.name(); // call named super constructor
some() {} // implement abstract method
}
main() {
print(new Foo()); // "instantiate" abstract Foo
}
輸出:
Instance of 'Bar'
問:「它是合理的編譯這樣的代碼?在Dart中並不是很有意義,因爲Dart是一種解釋型語言 - 沒有編譯階段。飛鏢編輯會發出警告,如果他們認爲你正在犯一個類型錯誤,他們分析你的代碼在飛行中。
工廠構造函數可用於提供抽象類的「默認」具體實現,就像您在示例中所做的那樣。這在Dart中被廣泛使用。例如,如果創建新的Map
對象,則實際上會得到LinkedHashMap
對象 - 請參閱this question and answer。
在你的例子中,你沒有實例化一個Foo
('new Foo'沒有出現在任何地方)的實例,你正在實例化一個Bar。這是因爲當調用工廠構造函數時,其類的新實例不會自動實例化。
由於dart2js編譯,Dart也是一種編譯語言。總的來說,編譯或解釋一個* language *並不總是合情合理的,因爲通常可以同時使用這兩種語言,而許多「解釋器」實際上都是場景後面的JIT編譯器。 – lrn 2014-11-21 06:15:35
如果你去https://www.dartlang.org/docs/dart-up-and-running/ch02.html並搜索「編譯」字符串,你將得到18個結果... – 2014-11-21 10:00:08
採取的點。我傾向於將Dart編譯爲JS作爲最終代碼生成步驟,與將Java編譯爲字節碼或C++到目標文件截然不同。 – 2014-11-21 15:06:31