dart语言和java语言
As a full-stack developer, I have to switch between several programming languages in my day-to-day business: Java (backend), TypeScript (web dev) and Dart (mobile dev). In this blog post, I will try to demonstrate fourteen built-in language constructs in TypeScript and Dart which convinced me to believe that these languages are more sophisticated and flexible than Java. You can already see in the picture above how fluent you can build collections in Dart using conditionals and repetition. These features are called “collection for” and “collection if”. Neat? But there are more. As you could also see, the type information in Dart is preserved at runtime. The check if the variable listOfStrings
has the type List<String>
works fine at runtime. In contrast, Java has type erasure, which means that generic type parameters are removed at runtime. In Java, you can’t test directly whether a collection is of type List<String>
.
作为全栈开发人员,我必须在日常业务中切换几种编程语言:Java(后端),TypeScript(Web开发)和Dart(移动开发)。 在这篇博客文章中,我将尝试演示TypeScript和Dart中的 14种内置语言构造,这使我相信这些语言比Java更复杂和灵活。 您已经在上图中看到了使用条件和重复在Dart中构建收藏集的流利程度。 这些功能称为“收集为”和“收集为”。 整齐? 但是还有更多。 您还可以看到,Dart中的类型信息在运行时保留。 检查变量listOfStrings
是否具有类型List<String>
在运行时可以正常工作。 相反,Java具有类型擦除 ,这意味着在运行时会删除通用类型参数。 在Java中,您不能直接测试集合的类型是否为List<String>
。
After reading this blog post, you will notice that people behind TypeScript and Dart spent much time in language design to make them user-friendly. In this article, we will cover:
阅读此博客文章后,您会发现TypeScript和Dart背后的人们在语言设计上花费了很多时间,以使其易于使用。 在本文中,我们将介绍:
- String interpolation 字符串插值
- Multiline strings 多行字符串
- Parameter properties in constructor 构造函数中的参数属性
- Optional parameters 可选参数
- Default parameter values 默认参数值
- Null-aware operators 空感知运算符
- Spread operator 点差运算符
- Indistinguishability of fields and getters / setters 字段和获取器/设置器的不可区分性
- Mixins (aka multiple inheritance) Mixins(又名多重继承)
- Dynamic extensions of existing types 现有类型的动态扩展
- Asynchronous programming with async / await 异步编程/异步
- Generators 发电机
- Control flow analysis 控制流分析
- Method chaining (amazing builder pattern!) 方法链接(惊人的构建器模式!)
You can try all code snippets in TypeScript Playground or DartPad respectively.
您可以分别在TypeScript Playground或DartPad中尝试所有代码段。
1.字符串插值 (1. String interpolation)
String interpolation is a process of evaluating the final string by injecting a variable or an expression in a string literal.
字符串插值是通过在字符串文字中注入变量或表达式来评估最终字符串的过程。
打字稿 (TypeScript)
The string interpolation is an ECMAScript 2015 (ES6) feature. It works by using${variable}
or ${expression}
syntax. An example:
字符串插值是ECMAScript 2015(ES6)功能。 它通过使用${variable}
或${expression}
语法来工作。 一个例子:
镖 (Dart)
In Dart, you can use $variable
or ${variable}
syntax for the string interpolation. The variable itself can be of any type. The expression in ${}
can be used as well.
在Dart中,可以对字符串插值使用$variable
或${variable}
语法。 变量本身可以是任何类型。 ${}
的表达式也可以使用。
Dart internally calls
toString()
on objects that are being interpolated.Dart在要内插的对象上内部调用
toString()
。
Sure, in Java you can leverage String.format(...)
but built-in language constructs in TypeScript and Dart are shorter and more concise.
当然,在Java中,您可以利用String.format(...)
但是TypeScript和Dart中的内置语言结构更短,更简洁。
2.多行字符串 (2. Multiline strings)
打字稿 (TypeScript)
Multiline strings is an ES6 feature. They can be created with a backtick (`) at begin and end of a string. No + sign is necessary for string concatenation.
多行字符串是ES6的功能。 可以在字符串的开头和结尾使用反引号(`)来创建它们。 字符串连接不需要+号。
镖 (Dart)
The Dart’s way to create a multiline string is a triple quote with either single or double quotation marks.
Dart创建多行字符串的方式是用单引号或双引号引起来的三重引号。
Furthermore, if you have two string literals, you do not need to use + to concatenate them. Example:
此外,如果您有两个字符串文字,则无需使用+来串联它们。 例:
3.构造函数中的参数属性 (3. Parameter properties in constructors)
Parameter properties in constructors let you create and initialize a class member in one place.
构造函数中的参数属性使您可以在一处创建和初始化类成员。
打字稿 (TypeScript)
Parameter properties are declared by prefixing a constructor parameter with an accessibility modifier or readonly
, or both. For example, instead of
通过使用可访问性修饰符或readonly
或两者都为构造函数参数加上前缀来声明参数属性。 例如,代替
just write
写就好了
镖 (Dart)
In Dart, this feature is called “initializing formals”. Just use the this.
syntax before a constructor parameter. The main rule of effective Dart is: do use initializing formals when possible.
在Dart中,此功能称为“初始化形式”。 只需使用this.
构造函数参数之前的语法。 有效Dart的主要规则是:尽可能使用初始化形式。
Note that in Dart you can not omit the property declaration (see the code snippet above). But in Dart you can use
;
instead empty constructor body{}
.请注意,在Dart中,您不能省略属性声明(请参见上面的代码段)。 但是在Dart中你可以使用
;
而是使用空的构造函数主体{}
。
Saidy, but this simple and handy feature is missing completely in Java.
Saidy,但是此简单易用的功能在Java中完全缺失。
4.可选参数 (4. Optional parameters)
Optional parameters are optional in that the caller isn’t required to specify a value for the parameter when calling a function.
可选参数是可选的,因为在调用函数时不需要调用者为参数指定值。
打字稿 (TypeScript)
In TypeScript, we can specify that a property (in interfaces / classes) or a parameter (in functions) is optional with a question mark (?) after the name. Optional parameters are especially handy in functions. An example:
在TypeScript中,我们可以指定属性(在接口/类中)或参数(在函数中)是可选的,名称后带有问号(?)。 可选参数在功能上特别方便。 一个例子:
镖 (Dart)
Optional parameters in Dart can be named and positional. A parameter wrapped by [ ]
is a positional optional parameter. A parameter wrapped by { }
is a named optional parameter. Named parameters can be referenced by names when invoking a function. Values for named parameters can be passed in any order, when invoking the function (this is the main benefit of them). The required parameters are listed first, followed by any optional parameters.
Dart中的可选参数可以命名为 positional 。 [ ]
包裹的参数是位置可选参数。 由{ }
包裹的参数是命名的可选参数。 调用函数时,可以通过名称引用命名参数。 调用函数时,可以按任何顺序传递命名参数的值(这是它们的主要优点)。 首先列出必需的参数,然后列出所有可选参数。
5.默认参数值 (5. Default parameter values)
An optional parameter can have a default value which is used when a caller does not specify a value. Such default values are provided after the =
operator.
可选参数可以具有默认值,该默认值在调用方未指定值时使用。 此类默认值在=
运算符之后提供。
打字稿 (TypeScript)
The TypeScript example above can be rewritten now as
上面的TypeScript示例现在可以重写为
The function invocation at the default value’s position can be placed as well. By this way, the default value can be calculated at runtime.
也可以将函数调用放在默认值的位置。 通过这种方式,可以在运行时计算默认值。
镖 (Dart)
The example with the optional parameter port
can be rewritten as
带有可选参数port
的示例可以重写为
6.空感知运算符 (6. Null-aware operators)
There are two null-aware operators which work almost similar in TypeScript and Dart and allow us to write a compact code.
有两个null感知运算符,它们在TypeScript和Dart中的工作原理几乎相似,并允许我们编写紧凑的代码。
Optional chaining operator
?.
可选的链接运算符
?.
The logical nullish coalescing operator
??
逻辑无效合并运算符
??
打字稿 (TypeScript)
The optional chaining and nullish coalescing operators are new ECMAScript features. Optional chaining lets us write code where TypeScript can immediately stop running some expressions if we run into a null
or undefined
. Let's write a code snippet with and without the optional chaining operator.
可选的链接和无效合并运算符是ECMAScript的新功能。 可选的链接使我们可以编写代码,如果遇到null
或undefined
,TypeScript可以立即停止运行某些表达式。 让我们编写一个带有和不带有可选链接运算符的代码段。
The nullish coalescing operator returns its right-hand side operand when its left-hand side operand is null
or undefined
, and otherwise returns its left-hand side operand. For example:
当空的合并运算符的左侧操作数为null
或undefined
,将返回其右侧操作数,否则返回其左侧操作数。 例如:
This is a new way to say that the value foo
will be used when it's "present"; but when it's null
or undefined
, calculate bar()
in its place. The above code is equivalent to
这是一种新的方式来表示值foo
将在“存在”时使用; 但是当它为null
或undefined
,请在其位置计算bar()
。 上面的代码相当于
镖 (Dart)
In Dart, alle properties and variables are initialized with null
per default (every type is an object). Use ?.
when you want to call a method or access a property on an nullable object. If the object is null
, the result of the method invocation or property accessing is also null
. The syntax with the null-aware ??
operator is expr = expr1 ?? expr2
. If expr1
is non-null, returns its value; otherwise, evaluates and returns the value of expr2
. With null-aware operators you can do nice things like this one:
在Dart中,默认情况下alle属性和变量初始化为null
(每种类型都是一个对象)。 使用?.
当您要调用方法或访问可为空的对象上的属性时。 如果对象为null
,则方法调用或属性访问的结果也为null
。 具有null感知的语法??
运算符是expr = expr1 ?? expr2
expr = expr1 ?? expr2
。 如果expr1
不为null,则返回其值; expr1
,返回0。 否则,求值并返回expr2
的值。 使用了解空值的运算符,您可以执行以下操作:
7.点差运算符 (7. Spread operator)
The syntax of the spread operator is three dots (...
) followed by an iterable object. It expands the iterable object into individual elements.
扩展运算符的语法是三个点( ...
),后跟一个可迭代的对象。 它将可迭代对象扩展为单个元素。
打字稿 (TypeScript)
The spread operator can be used to expand an array in a places where zero or more elements are expected. Using this, we can e.g. merge two or more arrays or objects. Examples:
散布运算符可用于在期望零个或多个元素的地方扩展数组。 使用此方法,我们可以例如合并两个或多个数组或对象。 例子:
镖 (Dart)
The spread operator in Dart provides a concise way to insert multiple elements into a collection. You can use this operator to insert all elements of a collection into another collection. There is also a null-aware spread operator ...?
which helps to avoid exceptions when to be inserted collection is null
.
Dart中的传播运算符提供了一种简洁的方法,可以将多个元素插入到集合中。 您可以使用此运算符将一个集合的所有元素插入另一个集合。 还有一个空感知的传播算子...?
这有助于避免在插入collection时为null
异常。
8.字段和获取器/设置器的不可区分性 (8. Indistinguishability of fields and getters / setters)
Getters and setters provide access to the properties of an object. In Java, it’s common to hide all fields behind getters and setters, even if the implementation just forwards to the field. Calling a getter method is different than accessing a field in Java. Getters and setters have different names than the corresponding field names. For example, if you have a field name
, the getter would be getName()
and the setter setName(String name)
. Just look at this example in Java:
使用Getter和Setter可以访问对象的属性。 在Java中,通常将所有字段隐藏在getter和setter后面,即使实现只是转发到该字段也是如此。 调用getter方法与访问Java中的字段不同。 获取器和设置器的名称与对应的字段名称不同。 例如,如果您有一个字段name
,则getter将是getName()
,而设置方法是setName(String name)
。 只要看一下Java中的这个例子:
In TypeScript and Dart, the getters and setters have the same names as the corresponding fields. You can expose a field in a class and later wrap it in a getter and setter without having to touch any code that uses that field. We can say — fields and getters / setters are completely indistinguishable. Let’s look at code snippets in these languages.
在TypeScript和Dart中,getter和setter的名称与相应字段的名称相同。 您可以在一个类中公开一个字段,然后将其包装在一个getter和setter中,而无需触摸任何使用该字段的代码。 我们可以说-字段和获取器/设置器是完全无法区分的。 让我们看一下这些语言的代码片段。
打字稿 (TypeScript)
Please note, you don’t have to use the method here, just assign the value directly.
请注意,您不必在这里使用方法,只需直接分配值即可。
镖 (Dart)
Effective Dart recommends: DON’T wrap a field in a getter and setter unnecessarily.
有效的Dart建议:不要将字段不必要地包装在getter和setter中。
9. Mixins (9. Mixins)
Mixin is the process of combining multiple classes to a single target class. It is intended to overcome the limitations of single inheritance model. In Java, TypeScript an Dart, we can’t inherit or extend from more than one class with extends
but mixins in TypeScript and Dart helps us to get around that. Mixins create partial classes which we can combine to form a single class that contains all the methods and properties from the partial classes. From a mathematical point of view, one can say that the classic, single super-class inheritance creates a tree (left picture). And mixin pattern creates a directed acyclic graph (right picture).
Mixin是将多个类组合为单个目标类的过程。 旨在克服单一继承模型的局限性。 在Java中,打字稿的Dart,我们不能继承或一个以上的类扩展与extends
,但在打字稿及Dart混入帮助我们要解决这个问题。 Mixins创建子类,我们可以将它们组合成一个单独的类,其中包含子类中的所有方法和属性。 从数学的角度来看,可以说经典的单一超类继承创建了一棵树(左图)。 mixin模式创建有向无环图(右图)。
Composing partial behaviors with mixins in both languages is different.
用两种语言的mixins构成部分行为是不同的。
打字稿 (TypeScript)
Let’s create a Timestamped
mixin that tracks the creation date of an object in a timestamp
property:
让我们创建一个带有Timestamped
mixin,它在timestamp
属性中跟踪对象的创建日期:
Let’s create a User
class now.
现在创建一个User
类。
Finally, we create a new class by mixing Timestamped
into User
.
最后,我们通过将Timestamped
混合到User
创建一个新类。
镖 (Dart)
In Dart, we can use the with
keyword on every class we want to extend with additional properties and behaviors. Assume, we have a class Person
.
在Dart中,我们可以在每个要扩展的类上使用with
关键字,并附加其他属性和行为。 假设我们有一个Person
类。
Let’s define a class Learner
having one method learn()
and a class Student
which will extend Person
and include everything from theLearner
.
让我们定义一个具有一个方法learn()
Learner
类和一个将扩展Person
并包括该Learner
所有内容的Student
类。
An instance of type Student
can now access both methods info()
(from Person
) and learn()
(from Learner
).
现在,类型为Student
的实例可以访问info()
(来自Person
)和learn()
(来自Learner
)这两种方法。
10.现有类型的动态扩展 (10. Dynamic extensions of existing types)
Dynamic extensions are a way to add additional functionality to existing libraries without touching them. That means, if you have e.g. a class in a third-party library, you can extend it without changing the class or creating a subclass. This is a killer feature in my opinion which makes a language attractive. There is no something similar in Java at the time of writing.
动态扩展是一种在不影响现有库的情况下向其添加其他功能的方法。 这意味着,如果您在第三方库中有一个类,则可以在不更改该类或创建子类的情况下对其进行扩展。 我认为这是一项杀手级功能,使一种语言更具吸引力。 撰写本文时,Java中没有类似的东西。
打字稿 (TypeScript)
TypeScript allows merging between multiple types such as interface
with interface
, enum
with enum
, namespace
with namespace
. This feature is called declaration merging. Declaration merging is when the TypeScript complier merges two or more types into one declaration provided the same name. Example:
TypeScript允许在多个类型之间进行合并,例如interface
与interface
, enum
与enum
, namespace
与namespace
。 此功能称为声明合并 。 声明合并是指TypeScript编译器将两个或多个类型合并为一个提供相同名称的声明。 例:
Why use declaration merging and where does it shine?
为什么要使用声明合并,它在哪里发光?
- You can extend declarations of third-party libraries that you import into your project. 您可以扩展导入到项目中的第三方库的声明。
- You can extend declarations of generated TypeScipt definitions, which are usually coming from backend. In my project, we generate TypeScript code from plain Java objects by a Maven plugin. 您可以扩展生成的TypeScipt定义的声明,这些声明通常来自后端。 在我的项目中,我们通过Maven插件从普通Java对象生成TypeScript代码。
TypeScript uses merging to get different types for the different versions of JavaScript’s standrad libraries. Example: the
Array
interface. It is defined in lib.es5.d.ts file. By default this is all you get. But if you add ES2015 to the lib entry of your tsconfig.json, TypeScript will also include lib.es2015.d.ts. This includes anotherArray
interface with additional methods likefind
that were added in ES2015. They get added to the otherArray
interface via merging.TypeScript使用合并为JavaScript的不同版本的standrad库获取不同的类型。 示例:
Array
接口。 它在lib.es5.d.ts文件中定义。 默认情况下,这就是您所获得的。 但是,如果你添加ES2015你tsconfig.json的lib项,输出文件也包括lib.es2015.d.ts。 这包括另一个Array
接口,以及ES2015中添加的其他方法(如find
。 通过合并将它们添加到另一个Array
接口。
One project where I was involved and used this technique: OffscreenCanvas by “Definitely Typed” — the repository for high quality TypeScript type definitions.
我参与并使用了该技术的一个项目: “ Definitely Typed”的OffscreenCanvas-高质量TypeScript类型定义的存储库。
镖 (Dart)
In Dart there is also a way to add functionality to existing libraries. This feature is called extension methods. The syntax is extension [<Name>] on <Type> {<Methods>}
. The name after the keyword extension
is optional. Let’s see some examples how to extend the type int
.
在Dart中,还有一种向现有库添加功能的方法。 此功能称为扩展方法 。 语法是extension [<Name>] on <Type> {<Methods>}
。 关键字extension
名后的名称是可选的。 让我们看一些如何扩展int
类型的示例。
Now, we can directly call toBinaryString()
on every integer. There are two implementations of the method str()
— in this case, we should wrap an integer by the extension name to enables the unambiguous identification of the extension.
现在,我们可以直接在每个整数上调用toBinaryString()
。 方法str()
有两种实现-在这种情况下,我们应该在扩展名旁边包装一个整数,以实现对扩展的明确标识。
Let’s see another example how to extend a generic List
.
让我们看另一个示例,如何扩展通用List
。
11.异步编程/异步 (11. Asynchronous programming with async / await)
A long time ago, an asynchronous behavior was modeled using callbacks. Having many nested callbacks led to so called callback hell or pyramid of doom. An example (pseudo code):
很久以前,异步行为是使用回调建模的。 有许多嵌套的回调导致所谓的回调地狱或毁灭金字塔 。 一个例子(伪代码):
Problems with callbacks:
回调问题:
- Execution order is the opposite of the code order. 执行顺序与代码顺序相反。
- The code is hard to read. 该代码很难阅读。
- Difficult to run requests in parallel. 难以并行运行请求。
Later, many programming languages introduced much better concepts to deal with asynchronism. JavaScript introduced the concept of a Promise to break the pyramid of doom. A Promise represent something that will be available in the future. Dart has the concept of Future. A Future represents the result of an asynchronous operation. It is waiting for the function’s asynchronous operation to finish or to throw an error. If the asynchronous operation succeeds, the Future completes with a value.
后来,许多编程语言引入了更好的概念来处理异步性。 JavaScript引入了Promise的概念来打破厄运金字塔。 一个Promise代表将来会可用的东西。 Dart具有Future的概念。 Future表示异步操作的结果。 它正在等待函数的异步操作完成或引发错误。 如果异步操作成功,则Future将以一个值完成。
What is about Java? Since Java 8 we have CompletableFuture. An example:
什么是Java? 从Java 8开始,我们有了CompletableFuture 。 一个例子:
The get
method waits for the computation to complete, and then retrieves its result. Can we write this kind of code better? Yes, in TypeScript and Dart we can write it better with async
and await
.
get
方法等待计算完成,然后检索其结果。 我们可以更好地编写这种代码吗? 是的,在TypeScript和Dart中,我们可以使用async
和await
更好地编写它。
打字稿 (TypeScript)
ES2017 introduced the async
and await
keywords which allow to write the code in a synchronous manner. Anawait
is used to wait for a promise to resolve or reject. It can only be used inside an async
function. Let’s rewrite the psedo-code above.
ES2017引入了async
和await
关键字,这些关键字允许以同步方式编写代码。 await
用于等待承诺解决或拒绝。 它只能在async
函数中使用。 让我们重写上面的psedo代码。
The await
keywords pause execution of the fetchPages
function until each Promise returned by fetch
resolves.
关键字await
暂停fetchPages
函数的执行,直到fetch
返回的每个Promise都解析为止。
镖 (Dart)
Thanks to Dart’s feature async / await
, you might never need to use the Future API directly. So, instead of
由于Dart具有async / await
功能,您可能永远不需要直接使用Future API。 所以,代替
you can write the code more straightforward
您可以更直接地编写代码
If you follow Dart’s best practice, the return value should be
Future<void>
.如果您遵循Dart的最佳做法,则返回值应为
Future<void>
。
12.发电机 (12. Generators)
Generators (more precisely generator functions) is a handy construct when you need to lazily produce a sequence of values. Both TypeScript and Dart have a built-in support of synchronous and asynchronous generators. With generators, we can create iterable objects where values come synchronously or asynchronously. A generator function is declared with an asterisk (*). A produced sequence of values is emitted with the yield
keyword. In this blog post, I will only show how to use asynchronous generators.
当您需要延迟生成值序列时, 生成器 ( 更 确切地说是 生成器函数 )是一种方便的构造。 TypeScript和Dart都具有对同步生成器和异步生成器的内置支持。 使用生成器,我们可以创建可迭代对象,其中值同步或异步出现。 生成器函数用星号(*)声明。 产生的值序列与yield
关键字一起发出。 在此博客文章中,我将仅展示如何使用异步生成器。
打字稿 (TypeScript)
If we execute a generator function, an object implementing iterable protocol is returned. The iterable protocol allows an object to be iterable. To iterate over such objects, we should use for … of
or for await … of
loop respectively. An asynchronous generator is an async
function with asterisk. The function body contains one or more await
operators. The await operator is used to wait for a promise to resolve or reject.
如果执行生成器函数,则返回实现可迭代协议的对象。 可迭代协议允许对象可迭代。 要遍历此类对象,我们应该分别使用for … of
或for await … of
循环。 异步生成器是带有星号的async
函数。 函数主体包含一个或多个await
操作符。 等待操作符用于等待承诺解决或拒绝。
镖 (Dart)
Dart has a similar concept as TypeScript. To implement an asynchronous generator function, mark the function body as async*
, and use yield
statements to deliver values. The return value is a Stream
object.
Dart与TypeScript具有相似的概念。 要实现异步生成器函数,请将函数主体标记为async*
,并使用yield
语句传递值。 返回值是一个Stream
对象。
13.控制流分析 (13. Control flow analysis)
Both TypeScript and Dart have an excellent support for control flow analysis. The type checker analyses all possible flows of control in statements and expressions to produce the most specific type possible at any given location for a local variable or parameter. Let’s create three classes Pet
, Dog
and Cat
in order to demonstrate the control flow analysis.
TypeScript和Dart都对控件流分析提供了出色的支持。 类型检查器分析语句和表达式中所有可能的控制流,以在任何给定位置为局部变量或参数生成最具体的类型 。 让我们创建三个类Pet
, Dog
和Cat
,以演示控制流分析。
打字稿 (TypeScript)
In TypeScript, you can create user defined type guards. User defined type guard is just a function that returns a type predicate in the form of someArgument is someType
. If the function returns true
, TypeScript will narrow the type, so that no cast is required.
在TypeScript中,您可以创建用户定义的类型Guard 。 用户定义的类型保护只是一个以someArgument is someType
形式返回类型谓词的函数。 如果函数返回true
,则TypeScript将缩小类型,因此不需要强制转换。
As you can see, in the if-statement, we can call bark()
without the cast to the Dog
. The type of the foo
was narrowed automatically by the TypeScript compiler.
如您所见,在if语句中,我们可以在不强制转换为Dog
情况下调用bark()
。 foo
的类型由TypeScript编译器自动缩小。
镖 (Dart)
To achieve the same result in Dart, we can use the type test operator is
. It returns true
if the object has the specified type.
为了在Dart中获得相同的结果,我们可以使用类型测试运算符is
。 如果对象具有指定的类型,则返回true
。
The Dart compiler narrows the type of the foo
without the typecast as
(as
operator is used to cast an object to a particular type).
Dart编译器将foo
的类型缩小为没有类型转换as
( as
运算符将对象转换为特定类型)。
14.方法链接 (14. Method chaining)
Method chaining allows you to apply a sequence of operations on the same object. Method chaining is often being used for building objects for classes having a lot of properties. A standard implementation of this approach in OOP languages is a builder pattern. Let’s implement a simple example in Java.
方法链接允许您对同一对象应用一系列操作。 方法链接通常用于为具有很多属性的类构建对象。 在OOP语言中这种方法的标准实现是构建器模式 。 让我们用Java实现一个简单的例子。
By returning this
, we can receive the class instance back immediately to call another method in the chain. There is a lot of code, even for this simple implementation without an inner public staticBuilder
class (a popular implementation of the builder pattern). TypeScript and Dart can save your time and offer more elegant constructs here.
通过返回this
,我们可以立即收到类实例,以调用链中的另一个方法。 即使没有这种简单的实现,也有很多代码,而没有内部公共静态Builder
类( Builder
器模式的流行实现)。 TypeScript和Dart可以节省您的时间,并在此处提供更优雅的构造。
打字稿 (TypeScript)
I like an implementation of the builder pattern with ES6 proxy. The Proxy
object enables you to create a proxy for another object, which can intercept and redefine operations for that object. See an explanation for more details. A generic implementation for every use case could be as follows:
我喜欢用ES6代理实现构建器模式。 Proxy
对象使您可以为另一个对象创建代理,该代理可以拦截和重新定义该对象的操作。 有关更多详细信息,请参见说明 。 每个用例的通用实现如下:
The usage is simple. For example:
用法很简单。 例如:
For more advanced generic implementation look this project on GitHub.
有关更高级的通用实现,请在GitHub上查看此项目 。
镖 (Dart)
Dart has a cascaded method invocation. Instead of .
notation, the cascade notation uses ..
(double-dot) in order to access current modifying instance. Assume, we have a class User
with setters / getters for most important fields. We can instantiate a User
instance as follows with the cascaded method invocation:
Dart具有级联方法调用。 代替.
表示法,级联表示法使用..
(双点)来访问当前的修改实例。 假设,我们有一个User
类,其中包含最重要字段的setters / getters。 我们可以使用级联方法调用实例化User
实例,如下所示:
By using cascade, we don’t have to put many of repeated return this
inside the class. But we can still return something else appropriate to the methods. Cascades can be nested as well. That allows even faster object buildings. See the example with nested cascades from the Dart language tour. This feature saves you the steps of creating temporary variables and allows you to write more fluid code.
通过使用层叠,我们不必在类中放入许多重复的return this
。 但是我们仍然可以返回适合该方法的其他内容。 级联也可以嵌套。 这样可以更快地建立对象。 请参阅Dart语言教程中有关嵌套级联的示例 。 此功能节省了创建临时变量的步骤,并允许您编写更多流畅的代码。
That’s all. Stay tuned!
就这样。 敬请关注!
dart语言和java语言