
| D | |
|---|---|
| 多范型 | |
|
面市時間
|
1999 |
|
设计者
|
Walter Bright |
| 最近释出日期 | 1.022 (稳定版)/ 2007年10月1日[1] |
| 强型态,静态 | |
|
主要实作产品
|
DMD, GDC |
|
启发语言
|
C, C++, C#, Java, Eiffel |
D 语言是由 Digital Mars 公司的 Walter Bright 所开发的面向对象、指令式、多范型系统程式设计语言。D 语言起源自 C++,并受到 C++ 很大的影响,不过 D 语言并不是 C++ 的变种。D 语言对 C++ 的部分特性重新设计,并受到其它编程语言观念的影响,如 Java、C# 以及 Eiffel。2007年1月2日释出 1.0 稳定版本。实验性版本 2.0 释出于 2007年1月17日。
Walter Bright 本身是 Symantec C++ 编译器的作者。
目录 |
D 的设计来自实际的 C++ 用法的经验教训,而不是从理论的角度。尽管 D 用到很多 C/C++ 观念,D 同时也废除了某部分,因此 D 并不完全向后相容 C/C++ 源代码。D 加入了 C++ 的功能,也实作了契约式设计(design by contract)、单元测试、真正的模组性、自动化内存管理(垃圾回收)、第一类阵列(first class array)、关联阵列、动态阵列、阵列切片、嵌套函式(巢状函式)、内部类别、闭包的限制形式、匿名函式、编译时期函式执行、惰性计算以及革新的模板语法。D 保有 C++ 的性能以进行低阶程式设计,并加入完整的内联组译器支援。C++ 的多重继承改以 Java 单继承与接口混合的风格取代。D 的宣告、语句和表达式语法几乎和 C++ 一样。
内联组译器(inline assembler)象征著 D 和 Java、C# 等应用编程语言的不同。内联组译器让程式员输入机器特定的组合语言码,如同标准 D 代码—通常由系统程式员使用的技术,以存取处理器的低阶功能,直接以硬件下的界面执行程式,如操作系统以及驱动程式。
D 内建支援文件注解,不过目前为止,只有 Digital Mars 实作版本有提供文件产生器。
D 支援三种主要的程式设计范型—指令式、面向对象以及元程式设计。
指令式程式设计几乎和 C 一样。函式、资料、语句、宣告以及表达式的运作就如同 C 一般,且可直接存取 C 执行时期程式库。
在 D 里面的面向对象程式设计,是以单继承分层结构,配合所有类别衍伸自类别物件为基础。多重继承可使用界面(界面很像 C++ 的抽象类别)。
以模板组合、编译时期函式执行、多元组以及字串混合来支援元程式设计。
内存通常以垃圾回收管理,不过当这些物件超出作用域时,可立即结束指定的物件。还是可以使用重载运算子 new 和 delete,以及简单的直接呼叫 C 的 malloc 和 free 以进行显示的内存管理。垃圾回收可禁用个别的物件或事件,以健全整个程式,如果在内存管理上有更多的控制,则更为理想。当垃圾回收在程式中有所不足时,手册还提供许多如何实作不同的高度最佳化内存管理方案的范例。
支援 C 的应用程式二进制接口(ABI),以及 C 的基本和衍伸型态,就能直接存取现有的 C 代码以及程式库。C 的标准函式库也是 D 标准的一部分。除非你使用非常清楚的命名空间,它可以稍微散乱的存取,因为它散布遍及于 D 模组—不过纯粹的 D 标准函式库也通常够用,除非要与 C 代码接合。
并未完整支援 C++ 的 ABI,尽管 D 可以存取写给 C ABI 的 C++ 代码,且可存取 C++ COM(元件物件模型)代码。D 语法分析器了解外部(C++)呼叫约定,以连结 C++ 物件,不过它只实作在目前的实验性 D 2.0。
D 2.0,D 的分支版本包含实验性特性,释出于2007年1月17日。其中一部分特性包括支援强制常数正确性(const-correctness),以及有限的支援连结以 C++ 编写的代码。
| 请协助扩充此章节。 更进一步的讯息可能会在或讨论页或扩充请求中找到。请在扩充章节后将此模板移除。 |
目前 D 实作直接编译成原生码以高效执行。
尽管 D 仍处于开发阶段,自 2007 年 1 月 的 1.0 版本,语言已不再定期的变更。目前的设计工作实质上已经停止,且新释出版本的着重在解决现存的错误。版本 1.0 不完全相容旧版本的语言和编译器。官方编译器由 Walter Bright 定义语言本身。
D 运算子重载在一定程度上不如 C++ 强大。简单的例子是 opIndex,它不允许返回参考。这使像是 obj[i] = 5; 的赋值不可能存在。D 的解决方法是 opIndexAssign 运算子,它只用于这种特殊情况。此外,C++ 返回参考的方法允许返回型态的重载赋值运算子的用法。这在目前的 D 还不可能做到。D 2.0 将会引入 opIndexLvalue 修正 - 类似运算子重载和 opIndexAssign。
结构在 D 之中是一种朴素旧式资料的型态,不过也可像变量一样包含方法。这对有意轻量化的建构而言相当实用,如矩阵或向量,这些不需要完整的 D 类别功能(以及体积)。然而,D 结构没有建构子和解构子。建构子可用静态 opCall 运算子部分取代,不过它没有适合的解构子等价物。此外,结构不允许继承,这会是有益的设计,如诡异循环模板模式(curiously recurring template pattern)的使用。
D 的标准函式库称作 Phobos,且时常被认为过分简单。tango 专案编写另一个标准函式库试图修正这一部分,不过 phobos 和 tango 目前由于不同的物件类别实作(导致垃圾回收困难)而互不相容。存在两种事实上的标准函式库可能导致更大的问题,部分软件使用 phobos,而其它软件使用 tango。
D 经常限于“修正并改进的 C++”。这会导致过分强调功能,这起因于加入新功能只是因为他们认为有用。举个例子,关联阵列可简单的以标准函式库实现。
Unix 的 ELF 共享函式库使用 GDC 编译器支援到某个程度。在 Windows 系统中,目前还不支援 DLL。因此现阶段不可能编写插件。不像 C++,经由 C 函式传送的 D 物件将不能运作,因为这将会与垃圾回收器产生冲突。
这个范例程式会输出它自己的命令列参数。main 函式是 D 程式的进入点,args 是表示为字串阵列的命令列参数。在 D 语言里的字串是一个字符阵列,以 char[] 表示。新版本中定义 string 为 char[] 的别名,不过别名定义必须与旧版本相容。
import std.stdio; // 以使用 writefln() alias char[] string; // 以相容舊的編譯器;新的編譯器中已隱含定義 int main(string[] args) { foreach(i, a; args) writefln("args[%d] = '%s'", i, a); return 0; }
foreach 语法可迭代所有的集合,在本例中,它从 args 阵列生成索引(i)和值(a)的序列。索引 i 和值 a 的型态会从 args 阵列的型态推断。
本例使用关联阵列建立更复杂的数据结构。
import std.stdio; // 以使用 writefln() alias char[] string; // 以相容舊的編譯器;新的編譯器中已隱含定義 int main(string[] args) { // 宣告以字串鍵和字串陣列作為資料的關聯陣列 string[] [string] container; // 將人們加入到容器中,並讓他們攜帶一些項目 container["Anya"] ~= "scarf"; container["Dimitri"] ~= "tickets"; container["Anya"] ~= "puppy"; // 迭代容器中所有的人 //Iterate over all the persons in the container foreach (string person, string[] items; container) display_item_count(person, items); return 0;//完成 } void display_item_count(string person, string[] items) { writefln(person, " is carrying ", items.length, " items."); }
本例繁多的注解显示出 D 语言与 C++ 的不同之处,以及仍然保留的方面。
#!/usr/bin/dmd -run /* 支援 sh 風格的 script 語法! */ /* D 語言的 Hello World * 進行編譯: * dmd hello.d * 或進行最佳化: * dmd -O -inline -release hello.d * 或產生文件: * dmd hello.d -D */ import std.stdio; // 參照常用的 I/O 例行工作。 alias char[] string; // 以相容舊的編譯器;新的編譯器中已隱含定義 int main(string[] args) { // 'writefln' (寫入-格式化-行,Write-Formatted-Line) 即型態安全的「printf」 writefln("Hello World, " // 自動連結的字串文字 "Reloaded"); // 字串即字元的動態陣列「char[]」,別名為「string」 // 自動的型態推斷,以及內建的 foreach foreach(argc, argv; args) { auto cl = new CmdLin(argc, argv); // 支援 OOP writefln(cl.argnum, cl.suffix, " arg: %s", cl.argv); // 使用者定義的類別屬性。 delete cl; // 垃圾回收或顯示的記憶體管理——由你自己選擇 } // 巢狀結構、類別和函式 struct specs { // 所有的變數會在執行時期自動初始化為 0 int count, allocated; // 不過你可選擇避開陣列的初始化 int[10000] bigarray = void; } specs argspecs(string[] args) // 可選用的(內建)函式契約。 in { assert(args.length > 0); // 內建 assert } out(result) { assert(result.count == CmdLin.total); assert(result.allocated > 0); } body { specs* s = new specs; // 不需要「->」 s.count = args.length; // 「length」屬性是元素的數量。 s.allocated = typeof(args).sizeof; // 原生型態內建的屬性 foreach(arg; args) s.allocated += arg.length * typeof(arg[0]).sizeof; return *s; } // 內建字串和普通的字串操作,例如「~」是連結。 string argcmsg = "argc = %d"; string allocmsg = "allocated = %d"; writefln(argcmsg ~ ", " ~ allocmsg, argspecs(args).count,argspecs(args).allocated); return 0; } /** * 儲存單獨命令列參數 */ class CmdLin { private { int _argc; string _argv; static uint _totalc; } public: /** * 物件的建構子。 * 參數: * argc = 參數的序列計數。 * argv = 參數內文。 */ this(int argc, string argv) { _argc = argc + 1; _argv = argv; _totalc++; } ~this() // 物件的解構子 { // 本例中不做任何事。 } int argnum() // 屬性,可返回參數數目 { return _argc; } string argv() // 屬性,可返回參數內文 { return _argv; } wstring suffix() // 屬性,可返回序數後綴 { wstring suffix; // 內建 Unicode 字串(UTF-8,UTF-16,UTF-32) switch(_argc) { case 1: suffix = "st"; break; case 2: suffix = "nd"; break; case 3: suffix = "rd"; break; default: // 'default' is mandatory with "-w" compile switch. suffix = "th"; } return suffix; } /** * 靜態屬性,如同在 C++ 或 Java 中, * 適用於類別物件,而不是實體。 * 返回:己加入的命令列參數總數。 */ static typeof(_totalc) total() { return _totalc; } // 類別不變量,任何方法在執行之後,這些必須為真。 invariant () { assert(_argc > 0); assert(_totalc >= _argc); } }
本例显示出一部分 D 语言强大的编译时期特性。
/* * D 語言裡的模板比 C++ 的要更加強大。 * 在此可以看到使用 static if(D 的編譯時期條件建構)簡單的建構出階乘模板。 */ template Factorial(ulong n) { static if( n <= 1 ) const Factorial = 1; else const Factorial = n * Factorial!(n-1); } /* * 這裡有一個正規的函式,可完成同樣的計算。 * 注意它們有多麼的相似。 */ ulong factorial(ulong n) { if( n <= 1 ) return 1; else return n * factorial(n-1); } /* * 終於,我們可以計算我們的階乘。注意,我們不需要去 * 明確的指定我們的常數的型態:編譯器有足夠的智能為 * 我們填充空白,因為它早已知道賦值中右手邊的型態。 */ const fact_7 = Factorial!(7); /* * 這是編譯時期函式評估的範例:普通函式可用於常數、 * 編譯時期表達式,假若它們滿足一定的條件。 */ const fact_9 = factorial(9); /*在此我們可以看到多麼強大的 D 模板:我們使用 * std.metastrings.Format 模板完成型態安全的 printf * 資料格式化,並使用 message pragma 顯示計算結果。 */ import std.metastrings; pragma(msg, Format!("7! = %s", fact_7)); pragma(msg, Format!("9! = %s", fact_9)); /* * 完成任務後,我們可以強制停止編譯。這樣的程式需是 * 從未實際編譯成可執行檔! */ static assert(false, "My work here is done.");
|
查 • 论 • 编 • 历
|
|
|---|---|
| 工业编程语言 | A+ - Ada - 汇编语言 - B - Brainfuck - COBOL - Curl - D - Eiffel - Erlang - FORTRAN - IronPython - Java - Jython - LISP - Lua - SCILAB - MATLAB - MATHEMATICA - Nuva - Oberon - OCaml - Perl - PHP - PostScript - Powerbuilder - Python - R - REXX - Ruby - Self - Smalltalk - Tcl/Tk - C# - F# - J# - Microsoft Visual C# |
| C/C++语言 | C - C++ - Turbo C++ - Borland C++ - C++ Builder- C++/CLI - Objective-C - Microsoft Visual C++ |
| BASIC语言 | BASIC - BASICA - GW-BASIC - QBASIC - QuickBASIC - True BASIC - Turbo BASIC - PowerBASIC - DarkBASIC - ETBASIC - GVBASIC Visual Basic .NET - Visual Basic - VBScript - VBA |
| Pascal/Delphi语言 | Pascal语法:(Pascal - Turbo Pascal - Object Pascal - Free Pascal) Pascal+Delphi语法:(Delphi) |
| ECMAScript方言 | ActionScript - DMDScript - JavaScript - JScript |
| GPU用着色器语言 | Cg - GLSL - HLSL |
| 学术编程语言 | APL/J - Clean - Haskell - Logo - ML - Prolog - Scheme - SAC |
| 数据库相关编程语言 | Clipper - Visual FoxPro - SQL - SQL預存程序 |
| 其他编程语言 | ALGOL - Forth - Modula-2/Modula-3 - MUMPS - PL/I - Simula |
Why are we here?
All text is available under the terms of the GNU Free Documentation License
This page is cache of Wikipedia. History