How to save DRY code in Golang

EDIT ++:

How not to repeat my code in Go?

type Animal interface { Kingdom() string Phylum() string Family() string } type Wolf struct {} type Tiger struct {} func (w Wolf) Kingdom() string {return "Animalia"} func (w Wolf) Phylum() string {return "Chordata"} func (w Wolf) Family() string {return "Canidae"} 

I have implemented three methods for the Wolf type, and I need to implement all the methods for the Tiger type to implement the interface. But the Kingdom and Phylum methods are the same for both types. It is somehow possible to implement only the Family method for the Tiger type:

 func (t Tiger) Family() string {return "Felidae"} 

and not repeat all three methods for each type?

Renouncement

Please do not confuse with simple return strings in methods, in the real case I need different implementations of the methods, and not just predefined values. Using this stupid style, I want to avoid the desecration of your brains. Therefore, skipping methods are not suitable at all. thanks

+6
source share
3 answers

This is a classic composition:

 type Wolf struct { Animalia Chordata Canidae } type Tiger struct { Animalia Chordata Felidae } type Animalia struct{} func (Animalia) Kingdom() string { return "Animalia" } type Chordata struct{} func (Chordata) Phylum() string { return "Chordata" } type Canidae struct{} func (Canidae) Family() string { return "Canidae" } type Felidae struct{} func (Felidae) Family() string { return "Felidae" } func main() { w := Wolf{} t := Tiger{} fmt.Println(w.Kingdom(), w.Phylum(), w.Family()) fmt.Println(t.Kingdom(), t.Phylum(), t.Family()) } 

Playground: https://play.golang.org/p/Jp22N2IuHL .

+8
source

This is very similar to misuse of interfaces. Interfaces do not replace classes; they are an expression of what a type can do. Here you have the data. Store data in structures.

 type Animal struct { kingdom string phylum string family string } var wolf = Animal{"Animalia", "Chordata", "Canidae"} var tiger = wolf tiger.family = "Felidae" 
+3
source

Since I am interested in the function, I read several articles on the topic and combined it into several reference points.

The attachment

Function named "embedding". And he solves the problem with repeated methods. Basic syntax:

 type Person struct { Name string } type Speaker struct { // Speaker is an abstract concept it has no name *Person // There is a type without field name. It is Anonymous. } 

Wrap and decoration

Yes, no OOP, but the code should be DRY anyway. The clearest way to think about this function is to wrap structures using methods. Thus, the surest way to describe anonymous fields is to use the decorator pattern (well known to Pythonistas).

 func (a *Speaker) Introduce(){ // But speaker can introduce itself fmt.Println(a.Name) // We have direct access to a wrapped struct attributes. } 

Merge and override

We can also combine methods implemented in structures

 func (s Speaker) Speak() string { return "Blah-blah" } type Den struct { // Combine Person and Speaker under Den struct Person Speaker } func (d Den) Speak() string { // Override Speak method only for Dennis return "I'm quit!" } func main() { den := Den{Person: Person{Name: "Dennis",}} mike := Speaker{Person: Person{Name: "Michael",}} fmt.Println(den.Introduce()) fmt.Println(den.Speak()) fmt.Println(mike.Introduce()) fmt.Println(mike.Speak()) } 

Thus, we can avoid the implementation of each required method for each type.

Interfaces

Same thing with interfaces. But if several interfaces are combined, this means that we do not need to declare methods that have already been declared in the interfaces used.

Playground

Dennis Suratna Blog Article

Documents

+2
source

Source: https://habr.com/ru/post/1011688/


All Articles