变量保存数据,方法通过托管表达式(第5章)来定义程序的行为。我们已经在每个代码例子中看过方法字段,前面的 HelloWorld示例就包含一个 main 方法:
While variables (4.1) hold data, methods are defining behavior of a program by hosting expressions (5). We have seen method fields in every code example of this document with even the initial Hello World (1.3) example containing a main method:
class Main {
static public function main():Void {
trace("Hello World");
}
}
方法通过 function 关键字识别。我们还可以了解到,它们:
Methods are identified by the function keyword. We can also learn that they
- 有一个名字(这里是main)
- 有一个参数列表(这里为 empty())
- 有一个返回类型(这里是 Void)
- 可能有访问修饰符(第4.4节)(这里是 static 和public)
- 可能有一个表达式(这里是 {trace("Hello World");})
- have a name (here: main),
- have an argument list (here: empty ()),
- have a return type (here: Void),
- may have access modifiers (4.4) (here: static and public) and
- may have an expression (here: {trace("Hello World");}).
还可以看下面的例子,了解更多参数和返回类型的知识:
We can also look at the next example to learn more about arguments and return types:
class Main {
static public function main() {
myFunc("foo", 1);
}
static function myFunc(f:String, i) {
return true;
}
}
参数通过字段名后一个开口的 ( 括号开始,一个 逗号 , 作为参数列表中每个参数的分隔符号,然后跟一个闭口的 ) 括号。参数规范的附加信息在 函数类型(第2.6节)中描述。
Arguments are given by an opening parenthesis ( after the field name, a comma , separated list of argument specifications and a closing parenthesis ). Additional information on the argument specification is described in Function Type (Section 2.6).
例子展示了类型推断如何被使用到两个参数和返回类型上。方法 myFunc 有两个参数,但是第一个被显式赋予类型,f,为String类型。第二个参数 i ,没有类型示意,留给编译器从它的调用中推断它的类型。此外,返回类型通过return ture 表达式来推断为 Bool 。
The example demonstrates how type inference(3.6) can be used for both argument and return types. The method myFunc has two arguments but only explicitly gives the type of the first one, f, as String. The second one, i, is not type-hinted and it is left to the compiler to infer its type from calls made to it. Likewise,the return type of the method is inferred from the return true expression as Bool.
重写字段是创建类的层级的结构。许多设计模式使用到它,但是这里我们只探索基本的功能。为了在类中使用重写,需要这个类有一个父类(第2.3.2)。思考下面的例子:
Overriding fields is instrumental for creating class hierarchies. Many design patterns utilize it, but here we will explore only the basic functionality. In order to use overrides in a class, it is required that this class has a parent class (2.3.2). Let us consider the following example:
class Base {
public function new() { }
public function myMethod() {
return "Base";
}
}
class Child extends Base {
public override function myMethod() {
return "Child";
}
}
class Main {
static public function main() {
var child:Base = new Child();
trace(child.myMethod()); // Child
}
}
这里重要的组件是:
The important components here are:
- Base 类,有一个方法 myMethod和一个构造函数
- Child类,继承Base类也有一个方法 myMethod,通过 override关键字声明
- Main 类,它的main方法创建一个Child类的实例,分配它到一个变量 child ,显式的声明类型为Base,然后在其上调用 myMethod()
- the class Base which has a method myMethod and a constructor,
- the class Child which extends Base and also has a method myMethod being declared with override, and
- the Main class whose main method creates an instance of Child, assigns it to a variable child of explicit type Base and calls myMethod() on it.
变量 child 被显式的类型化为 Base 来突出一个重要的不同:在编译器时类型被认为是 Base,但是运行时仍然查找正确的方法即类Child中的 myMethod。这是因为字段访问是在运行时动态解析的。
The variable child is explicitly typed as Base to highlight an important difference: At compile-time the type is known to be Base,but the runtime still finds the correct method myMethod on class Child. This is because field access is resolved dynamically at runtime.
Child 类可以访问它重载的方法,通过调用 super.methodName():
The Child class can access methods it has overriden by calling super.methodName():
class Base {
public function new() { }
public function myMethod() {
return "Base";
}
}
class Child extends Base {
public override function myMethod() {
return "Child";
}
public function callHome() {
return super.myMethod();
}
}
class Main {
static public function main() {
var child = new Child();
trace(child.callHome()); // Base
}
}
继承(第2.3.2节)中解释了super()在一个新的构造函数中的使用。
The section on Inheritance (Section 2.3.2) explains the use of super() from within a new constructor.
重载遵守变异(第3.4节)的规则。也就是说,它们的参数类型允许逆变(不那么特定的类型)而它们的返回类型允许共变(更特别的类型)。
Overriding adheres to the rules of variance (3.4). That is, their argument types allow contravariance (less specific types) while their return type allows covariance (more specific types):
class Base {
public function new() { }
}
class Child extends Base {
private function method(obj:Child):Child {
return obj;
}
}
class ChildChild extends Child {
public override function method(obj:Base):ChildChild {
return null;
}
}
class Main {
static public function main() { }
}
直观的说,这是因为参数被“写入”到函数中,而返回值是从函数中“读取”。
Intuitively, this follows from the fact that arguments are “written to” the function and the return value is “read from” it.
示例也展示了如何改变可见性(第4.4.1节):一个重载的字段可能是 public ,如果被重载的字段是private,但是相反则不行。
The example also demonstrates how visibility (4.4.1) may be changed: An overriding field may be public if the overridden field is private, but not the other way around.
不可能重载声明为内联(第4.4.2节)的字段。这是由于冲突的概念:当内联在编译时通过替换一个函数体的调用,重载字段必须被在运行时决定。
It is not possible to override fields which are declared as inline (4.4.2). This is due to the conflicting concepts: While inlining is done atcompile-time by replacinga call with thefunction body, overriding fields necessarily have to be resolved at runtime.