默认是模块级别,使用pub变为公共级别

    接口命名跟结构体一样,要求首字母大写,建议以er风格结尾,非强制

    接口字段

    接口在其他编程语言中大部分都只能包含方法签名

    V语言中接口除了可以包含方法签名,也可以包含字段,虽然包含字段也可以转为方法签名,

    编译时会检查结构体及其组合结构体(子类)是否实现接口字段,

    只有字段名,字段类型,是否可变,都跟接口中的字段一致,才算实现了这个接口字段.

    1. interface PointInterface {
    2. mut:
    3. x int //定义接口包含字段
    4. y int
    5. }
    6. struct Point {
    7. mut:
    8. x int //接口字段实现
    9. y int
    10. }
    11. fn add(p1 PointInterface,p2 PointInterface) PointInterface {
    12. mut p:=Point {}
    13. p.x=p1.x+p2.x
    14. p.y=p1.y+p2.y
    15. return p
    16. }
    17. fn main() {
    18. p1:=Point{
    19. x:1
    20. y:2
    21. }
    22. p2:=Point {
    23. x:3
    24. y:4
    25. }
    26. p3:=add(p1,p2)
    27. println('x:$p3.x,y:$p3.y')
    28. }
    1. interface Animal {
    2. mut:
    3. name string
    4. }
    5. struct Cat {
    6. name string //mut不匹配,编译不通过
    7. }
    8. fn main() {
    9. mut animals := []Animal{}
    10. animals << Cat{}
    11. }

    接口也可以像结构体那样有自己的方法,只要结构体实现了接口,就可以调用接口的方法

    接口组合

    接口也像结构体那样支持组合

    1. module main
    2. pub interface Reader{
    3. read(mut buf []byte) ?int
    4. }
    5. pub interface Writer {
    6. write(bug []byte) ?int
    7. }
    8. // 接口组合
    9. pub interface ReaderWriter {
    10. Reader
    11. Writer
    12. }
    13. //接口组合
    14. interface WalkerTalker {
    15. Walker
    16. }
    17. interface Talker {
    18. nspeeches int
    19. talk(msg string)
    20. interface Walker {
    21. nsteps int
    22. walk(newx int, newy int)
    23. }
    24. struct Abc {
    25. mut:
    26. x int
    27. y int
    28. phrases []string
    29. nsteps int = 1000 //实现接口中要求的字段
    30. nspeeches int = 1000 //实现接口中要求的字段
    31. }
    32. //实现接口要求的方法
    33. fn (mut s Abc) talk(msg string) {
    34. s.phrases << msg
    35. s.nspeeches++
    36. }
    37. //实现接口要求的方法
    38. fn (mut s Abc) walk(x int, y int) {
    39. s.x = x
    40. s.y = y
    41. s.nsteps++
    42. }
    43. fn main() {
    44. mut wt := WalkerTalker(Abc{
    45. x: 1
    46. y: 1
    47. phrases: ['hi']
    48. })
    49. wt.talk('my name is Wally')
    50. wt.walk(100, 100)
    51. if wt is Abc {
    52. println(wt)
    53. }
    54. }

    鸭子类型:只要结构体实现了接口定义的方法,就满足该接口的使用

    1. module main
    2. struct Dog {}
    3. struct Cat {}
    4. fn (d Dog) speak() string {
    5. return 'woof'
    6. }
    7. fn (c Cat) speak() string {
    8. return 'meow'
    9. }
    10. interface Speaker {
    11. speak() string
    12. }
    13. fn perform(s Speaker) {
    14. println(s.speak())
    15. }
    16. fn main() {
    17. dog := Dog{}
    18. cat := Cat{}
    19. perform(dog) // "woof"
    20. perform(cat) // "meow"

    接口可以作为结构体字段类型使用:

    获取接口变量的具体类型

    接口类型使用内置方法type_name()来返回接口变量的具体类型

    1. module main
    2. speak() string
    3. }
    4. pub struct Cat {}
    5. pub fn (c Cat) speak() string {
    6. return 'miao'
    7. }
    8. pub struct Dog {}
    9. pub fn (d Dog) speak() string {
    10. return 'wang'
    11. }
    12. pub fn say(animal Animal) {
    13. println(typeof(animal).name) // 只会返回接口名字Animal,不会返回具体类型
    14. println(animal.type_name()) // 返回接口的具体类型
    15. println(animal.speak())
    16. }
    17. fn main() {
    18. cat:=Cat {}
    19. say(cat)
    20. dog:=Dog{}
    21. say(dog)
    22. }

    使用is,!is对接口参数的具体类型进行判断

    使用match对接口类型参数进行匹配,跟match匹配联合类型一样,每一个分支都会自动造型,非常的好用

    1. module main
    2. struct Dog {
    3. name1 string
    4. }
    5. struct Cat {
    6. name2 string
    7. }
    8. fn (d Dog) speak() string {
    9. return 'wang'
    10. }
    11. fn (c Cat) speak() string {
    12. return 'miao'
    13. }
    14. interface Speaker {
    15. speak() string
    16. }
    17. fn perform(s Speaker) {
    18. if s is Dog { // 通过is操作符,判断接口类型是否是某一个具体类型
    19. println('s is Dog')
    20. }
    21. if s !is Dog { // 通过!is操作符,判断接口类型不是某一个具体类型
    22. println('s is not Dog')
    23. }
    24. //match对接口参数的类型匹配,跟匹配联合类型一样,每一个分支都会自动造型,非常的好用
    25. match s {
    26. Dog { println('s is Dog struct,name is $s.name1') }
    27. Cat { println('s is Cat struct,name is $s.name2') }
    28. else { println('s is: $s.type_name()') }
    29. }
    30. }
    31. fn main() {
    32. dog := Dog{ name1:'dog' }
    33. cat := Cat{ name2:'cat' }
    34. perform(dog) // "wang"
    35. perform(cat) // "miao"

    判断类型是否实现接口