Interface for GO Foundation

1. Concepts
1. In object-oriented languages, interfaces are used to define the behavior of objects.Interfaces only specify what the object should do, and the way to implement this behavior (implementation details) is determined by the object.
2. In the Go language, an interface is a set of method signatures.

  • Interfaces specify only the methods that a type should have, and the type determines how those methods are implemented.
  • When a type provides specific implementation details for all methods in an interface, it is called an implementation of the interface.
  • An interface defines a set of methods that an object implements if it implements all the methods of the interface.

3. The types of Go Language implements interfaces implicitly.Any type that defines all methods in an interface is referred to as implicitly implementing the interface.

 

2. Use of interfaces

go has no implements, extends keyword. In fact, this programming language is called duck typing programming language.

package main

import "fmt"
import "base"

//Define interfaces
type Phone interface {
    call()
}

type AndroidPhone struct {
}

type IPhone struct {
}

func (a AndroidPhone) call() {
    fmt.Println("I'm an Android phone and can make a call")
}

func (i IPhone) call() {
    fmt.Println("I'm an Apple phone, so I can call")
}

func main() {
    //    Variables defining interface types
    var phone Phone
    //phone = new(AndroidPhone)
    phone = AndroidPhone{}
    fmt.Printf("%T , %v , %p \n" , phone , phone , &phone)
    phone.call()

    //phone = new(IPhone)
    phone = IPhone{}
    fmt.Printf("%T , %v , %p \n" , phone , phone , &phone)
    phone.call()
}


Dynamic and Static Type Languages

  • * Dynamic types offer many benefits, Python code writes quickly.But the drawbacks are also obvious: errors are often discovered at runtime.
  • Conversely, statically typed languages tend to find these errors at compile time: if the type of a variable does not explicitly declare that it implements an interface, then the variable cannot be used where it is required to implement that interface.

A compromise has been taken for the Go type system:
* This is a compromise for the following reasons:

  • Firstly, struct type T does not need to explicitly declare that it implements interface I.As long as type T implements all the methods specified in interface 1, it automatically implements interface I.This saves a lot of code and limitations just like dynamic languages.
  • Second, the variable of the structure type is explicitly or implicitly converted to the variable i of the interface type i.This allows you to check the validity of parameters at compile time, just like other static type languages.

3. Polymorphism

* Multiple forms of things

  • * Polymorphisms in Go s are achieved with the help of an interface.Defines the interface type and stores the structure object that implements the interface.
  • An object that defines an interface type and can hold values of any type that implements that interface.This feature of the Go language interface variable implements polymorphism in the Go language.
  • * Objects of interface type cannot access property fields in their implementation classes.

 

package main

import "fmt"
import "base"


type Income interface {
    calculate() float64 //Calculate gross revenue
    source() string     //Used to illustrate revenue sources
}

//Fixed Bill Items
type FixedBilling struct {
    projectName  string  //Project Projects
    biddedAmount float64 //Total project tender
}

//Timed Production Projects(Timing and material projects)
type TimeAndMaterial struct {
    projectName string
    workHours   float64 //Working hours
    hourlyRate  float64 //Hourly rate
}

//Fixed Income Project
func (f FixedBilling) calculate() float64 {
    return f.biddedAmount
}

func (f FixedBilling) source() string {
    return f.projectName
}

//Timed Income Project
func (t TimeAndMaterial) calculate() float64 {
    return t.workHours * t.hourlyRate
}

func (t TimeAndMaterial) source() string {
    return t.projectName
}

//Revenue from ad clicks
type Advertisement struct {
    adName         string
    clickCount     int
    incomePerclick float64
}

func (a Advertisement) calculate() float64 {
    return float64(a.clickCount) * a.incomePerclick
}

func (a Advertisement) source() string {
    return a.adName
}

func main() {
    p1 := FixedBilling{"Item 1", 5000}
    p2 := FixedBilling{"Item 2", 10000}
    p3 := TimeAndMaterial{"Item 3", 100, 40}
    p4 := TimeAndMaterial{"Item 4", 250, 20}
    p5 := Advertisement{"Advertising 1", 10000, 0.1}
    p6 := Advertisement{"Advertising 2", 20000, 0.05}

    ic := []Income{p1, p2, p3, p4, p5, p6}
    fmt.Println("total=",calculateNetIncome(ic))
}

//Calculate net income
func calculateNetIncome(ic []Income) float64 {
    netincome := 0.0
    for _, income := range ic {
        fmt.Printf("Income source:%s ,Income amount:%.2f \n", income.source(), income.calculate())
        netincome += income.calculate()
    }
    return netincome
}

 

4. Empty interfaces

* Empty interface: There are no methods in this interface.Any type can implement the interface.
* An empty interface is defined as an interface {}, which contains 0 method s.
* Represent any data type with an empty interface.Similar to object s in java.
* Empty interfaces are commonly used in the following situations:
Parameters of 1 and println are empty interfaces
2, Define a map: key is a string, value is any data type
3. Define a slice that stores any type of data

package main

import (
    "fmt"
)

type A interface {
}

type Cat struct {
    name string
    age  int
}

type Person struct {
    name string
    sex  string
}

func main() {
    var a1 A = Cat{"Mimi", 1}
    var a2 A = Person{"Steven", "male"}
    var a3 A = "Learn golang with me!"
    var a4 A = 100
    var a5 A = 3.14

    showInfo(a1)
    showInfo(a2)
    showInfo(a3)
    showInfo(a4)
    showInfo(a5)
    fmt.Println("------------------")

    //1,fmt.println Parameter is an empty interface
    fmt.Println("println The parameter is an empty interface and can be any data type", 100, 3.14, Cat{"Wangwang", 2})

    //2,Definition map. value Is any data type
    map1 := make(map[string]interface{})
    map1["name"] = "Daniel"
    map1["age"] = 13
    map1["height"] = 1.71
    fmt.Println(map1)
    fmt.Println("------------------")

    //    3,Define a slice that stores any data type
    slice1 := make([]interface{}, 0, 10)
    slice1 = append(slice1, a1, a2, a3, a4, a5)
    fmt.Println(slice1)

    transInterface(slice1)

    //var cat1 A = Cat{"MiaoMiao" , 3}
    //fmt.Println(cat1.name , cat1.age)

}

//Interface Object Transition
//Interface Object.(type),Coordination switch...case Sentence
func transInterface(s []interface{}) {
    for i := range s {
        fmt.Println("No.", i+1 , "Data:")
        switch t := s[i].(type) {
        case Cat:
            fmt.Printf("\t Cat Object, name Attributes:%s,age Attributes:%d \n" , t.name , t.age)
        case Person:
            fmt.Printf("\t Person Object, name Attributes:%s,sex Attributes:%s \n" , t.name , t.sex)
        case string:
            fmt.Println("\t string type" , t)
        case int:
            fmt.Println("\t int type" , t)
        case float64:
            fmt.Println("\t float64 type" , t)
        }
    }
}

func showInfo(a A) {
    fmt.Printf("%T , %v \n", a, a)
}

5. Transition of Interface Objects
1. Mode 1:
instance, ok: =interface object. (actual type)
* If the interface object is the corresponding actual type, then instance is the post-transition object and ok has a value of true
* Used with if... else if... statements
2. Mode 2:
* Interface object. (type)
* Used with switch...case statements

package main

import "fmt"
import (
    "base"
    "math"
)

//1,Define interfaces
type Shape interface {
    perimeter() float64
    area() float64
}

//2.rectangle
type Rectangle struct {
    a, b float64
}

//3.Triangle
type Triangle struct {
    a, b, c float64
}

//4.circular
type Circle struct {
    radius float64
}

//Define methods to implement interfaces
func (r Rectangle) perimeter() float64 {
    return (r.a + r.b) * 2
}

func (r Rectangle) area() float64 {
    return r.a * r.b
}

func (t Triangle) perimeter() float64 {
    return t.a + t.b + t.c
}

func (t Triangle) area() float64 {
    //Helen's Formula
    p := t.perimeter() / 2 //Half Perimeter
    return math.Sqrt(p * (p - t.a) * (p - t.b) * (p - t.c))
}

func (c Circle) perimeter() float64 {
    return 2 * math.Pi * c.radius
}

func (c Circle) area() float64 {
    return math.Pow(c.radius, 2) * math.Pi
}

//Interface Object Transition Mode 1
//instance,ok := Interface Object.(Actual type)
func getType(s Shape) {
    if instance, ok := s.(Rectangle); ok {
        fmt.Printf("Rectangle: Length%.2f , width%.2f , ", instance.a, instance.b)
    } else if instance, ok := s.(Triangle); ok {
        fmt.Printf("Triangle: Triangular:%.2f , %.2f , %.2f , ", instance.a, instance.b, instance.c)
    } else if instance, ok := s.(Circle); ok {
        fmt.Printf("Circle: Radius%.2f , ", instance.radius)
    }
}

//Interface Object Transition - Mode 2
//Interface Object.(type),  Coordination switch and case Statement Use
func getType2(s Shape) {
    switch instance := s.(type) {
    case Rectangle:
        fmt.Printf("Rectangle: Length is%.2f , Width is%.2f ,\t", instance.a, instance.b)
    case Triangle:
        fmt.Printf("Triangle: Three sides are%.2f ,%.2f , %.2f ,\t", instance.a, instance.b, instance.c)
    case Circle:
        fmt.Printf("Circle: radius is%.2f ,\t", instance.radius)
    }
}

func getResult(s Shape) {
    getType2(s)
    fmt.Printf("Perimeter:%.2f ,The measure of area:%.2f \n", s.perimeter(), s.area())
}

func main() {
    var s Shape
    s = Rectangle{3, 4}
    getResult(s)
    showInfo(s)

    s = Triangle{3, 4, 5}
    getResult(s)
    showInfo(s)

    s = Circle{1}
    getResult(s)
    showInfo(s)

    x := Triangle{3, 4, 5}
    fmt.Println(x)

}

func (t Triangle) String() string {
    return fmt.Sprintf("Triangle Object with the following attributes:%.2f, %.2f, %.2f", t.a, t.b, t.c)
}

func showInfo(s Shape) {
    fmt.Printf("%T ,%v \n", s, s)
    fmt.Println("-------------------")
}

Tags: Go Programming P4 Android

Posted on Thu, 07 Nov 2019 05:46:46 -0800 by melmoth