diff --git a/struct-interface.go b/struct-interface.go new file mode 100644 index 0000000..d72e62f --- /dev/null +++ b/struct-interface.go @@ -0,0 +1,236 @@ +// Copyright 2018 Gytis Repečka. All rights reserved. +// Use of this source code is governed by a GNU GPL +// license that can be found in the LICENSE file. + +package main + +import ( + "fmt" +) + +// Define named structures + +type CarMake struct { + makeTitle string + countryOfOrigin string +} + +type Car struct { + make CarMake + model string + year int + started bool +} + +type Truck struct { + modelName string + year int + started bool + weight int +} + +// Interfaces +/* +Interfaces are implemented implicitly +A type implements an interface by implementing its methods. There is no explicit declaration of intent, no "implements" keyword. +Implicit interfaces decouple the definition of an interface from its implementation, which could then appear in any package without prearrangement. +Good example of interfaces: https://gobyexample.com/interfaces +*/ +// Vehicle will act as interface to Car and Truck structs. +type Vehicle interface { + FriendlyName() string + Wheels() int + Start() +} + +// Functions (methods) + +// Receiving a pointer to Car/Truck so can modify it (change started value) + +// Start method for Car +func (c *Car) Start() { + c.started = true + fmt.Printf("Car %s %s says vrooom!\n", c.make.makeTitle, c.model) +} + +// Start method for Truck +func (t *Truck) Start() { + t.started = true + fmt.Printf("Truck %s (max cargo: %d t) says br br br br!\n", t.modelName, t.weight) +} + +// Because defined only for Car and not listed as method in +// type Vehicle interface, StopCar is applicable only for Car +// but not Vehicle. +func (c *Car) StopCar() { + if c.started == true { + c.started = false + fmt.Printf("Car %s %s was stopped.\n", c.make.makeTitle, c.model) + } else { + fmt.Printf("Car %s %s is not running anyway.\n", c.make.makeTitle, c.model) + } +} + +// This method is currently implemented for Car only. There is no implementation +// for Truck therefore cannot use this method for Vehicle. +func (cr *Car) AlterName(nameAppend string) (string) { + if nameAppend != "" { + cr.model = cr.model + " " + nameAppend + } + outString := fmt.Sprintf("%s %s (%d)", cr.make.makeTitle, cr.model, cr.year) + return outString +} + +// Car has 4 wheels +func (cr Car) Wheels() int { + return 4 +} + +// Truck has 6 wheels +func (tr Truck) Wheels() int { + return 6 +} +// ...and we can then use Wheels method to know how many wheels Vehicle has. + +func (cr Car) FriendlyName() (string) { + outStarted := "not running" + if cr.started == true { + outStarted = "vuu tuuuu tuuuuu" + } + outString := fmt.Sprintf("%s %s (%d) %s", cr.make.makeTitle, cr.model, cr.year, outStarted) + return outString +} + +func (t Truck) FriendlyName() (string) { + outStarted := "not running" + if t.started == true { + outStarted = "vuu tuuuu tuuuuu" + } + outString := fmt.Sprintf("%s (%d) %s", t.modelName, t.year, outStarted) + return outString +} + +// This method is for Vehicle therefore universal (not specifically for Car or +// for Truck). Mind that inside we can use only those methods which are defined +// for Vehicle (i.e. for Car and for Truck). +func VehicleDetails(vh Vehicle) { + fmt.Printf("Vehicle %s has %d wheels.\n", vh.FriendlyName(), vh.Wheels()) +} + +// This method is intended for interface Vehicle and works for both Car and Truck +func VehicleStart(vh Vehicle) { + fmt.Println("Starting vehicle [from interface method]...") + vh.Start() +} + + +// Main function (execution point) + +func main() { + var carMakes []CarMake + newCarMake := CarMake{makeTitle: "Toyota", countryOfOrigin: "Japan"} + carMakes = append(carMakes, newCarMake) + newCarMake = CarMake{makeTitle: "Renault", countryOfOrigin: "France"} + carMakes = append(carMakes, newCarMake) + newCarMake = CarMake{"Peugeot", "France"} + carMakes = append(carMakes, newCarMake) + + var cars []Car + newCar := Car{carMakes[1], "Clio", 1994, false} + cars = append(cars, newCar) + newCar = Car{carMakes[2], "406", 1997, false} + cars = append(cars, newCar) + newCar = Car{carMakes[0], "Yaris", 2000, false} + cars = append(cars, newCar) + + fmt.Println("--------------------------") + fmt.Println("Make | Model | Country") + fmt.Println("--------------------------") + + for i:=0; i