什么是接口?
在 Go 中,接口是一组方法签名。当类型为接口中的所有方法提供定义时,称为实现接口。它与 OOP 世界非常相似。接口指定类型应具有的方法,类型决定如何实现这些方法。
声明和实现接口
让我们直接进入一个创建接口并实现它的程序。
package main
import (
"fmt"
)
//interface definition
type VowelsFinder interface {
FindVowels() []rune
}
type MyString string
//MyString implements VowelsFinder
func (ms MyString) FindVowels() []rune {
var vowels []rune
for _, rune := range ms {
if rune == 'a' || rune == 'e' || rune == 'i' || rune == 'o' || rune == 'u' {
vowels = append(vowels, rune)
}
}
return vowels
}
func main() {
name := MyString("Sam Anderson")
var v VowelsFinder
v = name // possible since MyString implements VowelsFinder
fmt.Printf("Vowels are %c", v.FindVowels())
}
上面程序的第 8 行创建了一个名为 的接口类型,该接口类型具有一个方法。VowelsFinder
FindVowels() []rune
在下一行中,将创建一个类型:MyString
在第 15 行中,我们将方法 FindVowels() []rune
添加到接收器类型 MyString
。现在MyString
据说实现了接口VowelsFinder
。这与Java等其他语言完全不同,在Java中,类必须明确声明它使用关键字实现接口。这在 Go 中是不需要的,如果类型包含接口中声明的所有方法,则隐式实现 Go 接口。
在第 28 行中,我们将类型分配给 v 的类型。这是可能的,因为实现了接口。 在下一行中调用 FindVowels
方法并打印字符串中的所有元音。此程序输出
Vowels are [a e o]
下面来看pascal是如何实现上面接口的:
program InterfaceTest;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
rune = int32;
runes = TArray<rune>;
//interface definition
IVowelsFinder = interface
['{1E7F54C7-FE59-4D55-BC56-6F5E3174F838}']
function FindVowels(): runes;
end;
MyString = class(TInterfacedObject, IVowelsFinder)
private
Fms: string;
constructor Create(s: string);
public
function FindVowels(): runes;
end;
//MyString implements VowelsFinder
constructor MyString.Create(s: string);
begin
Fms := s;
end;
function MyString.FindVowels: runes;
var
vowels: runes;
_rune: Char;
i: Integer;
begin
i := 0;
for _rune in Fms do
begin
if (_rune = 'a') or (_rune = 'e') or (_rune = 'i') or
(_rune = 'o') or (_rune = 'u') then
begin
Inc(i);
SetLength(vowels, i);
vowels[i-1] := Integer(_rune);
end;
end;
Result := vowels
end;
procedure main;
var
name: MyString;
v: IVowelsFinder;
i: Integer;
vowel: runes;
begin
v := MyString.Create('Sam Anderson');
// possible since MyString implements VowelsFinder
vowel := v.FindVowels();
Write('Vowels are ');
for I := 0 to Length(vowel) - 1 do
Write(Char(vowel[i]));
SetLength(vowel, 0);
end;
begin
try
main{ TODO -oUser -cConsole Main : Insert code here }
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
delphi对于接口的实现,要比go复杂一点。按照固定的模式,先声明接口及其方法,然后定义一个实现此接口的Class。runes对应于go的[]rune,是个动态数组。在FindVowels函数中,以for...in语句遍历Fms,然后设置动态数组vowels的长度并赋值。
在C/C++中,此语句只会打印一个字符,但在go中可以打印出一个数组,说明go做了很大改进和优化。
fmt.Printf("Vowels are %c", v.FindVowels())
最终结果,go和pascal的输出是一样的。