is "translation" go an object-oriented language?

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

Original: http://spf13.com/post/is-go-object-oriented

Objective

To really understand the meaning of object-oriented, we need to review the origins of this concept. The first object-oriented language-simula was invented in the 1860s. It introduces concepts such as objects (object), classes (Class), Inheritance (inheritance), subclasses (subclass), virtual methods (virtual method), and co-processes (Coroutine). The most important contribution of Simula, however, may be that it introduces disruptive ideas-separating data and logic completely.

You may not be familiar with the Simula language, but you must be familiar with Java, C + +, C # & Smalltalk, which are deeply influenced by Simula, and of course these languages affect almost all of today's high-level languages such as Objective C, Python, Ruby, Javascript, Scala, PHP, Perl ... Most programmers follow the principle of separating data and logic completely.

Since there is no standard definition of object-oriented, we will provide a standard definition for the convenience of discussion.

Object-oriented systems integrate data and code together through "objects," rather than seeing programs as composed of detached data and code. An object is an abstraction of a data type that has state (data) and Behavior (code)

Object-oriented includes inheritance, polymorphism, virtual derivation, and so on, we will look at how the Go language handles objects, polymorphism, inheritance, and believe that after reading the next introduction, you will have your own insight into how go handles object orientation.

Objects in Go

There is no keyword in the Go Language for objects (object). An object is just a word, and what is important is the meaning it represents. Although there is no object type in go, the struct in go has the same characteristics as object.

A struct is a type that contains named fields and methods

Let's understand it from an example:

type rect struct {    width int    height int}func (r *rect) area() int {    return r.width * r.height}func main() {    r := rect{width: 10, height: 5}    fmt.Println("area: ", r.area())}

Let's take a line to explain the above code. The first block of code defines a struct type called rect that contains two fields of type int, and next defines an area method that is bound to a rect struct type. Strictly speaking, the area method is bound to a pointer to a RECTCT struct. If a method is bound to a rect type and not a pointer, then the value of that type is called when the method is called, even if the value is null, and the null value in this case is actually a nil value; the last block of the code is the main function, and the first row of the main function creates a rect-type value. Of course there are other ways to create a type of value, given here is an authentic method. The last line of the main function is to print the return result of the area method acting on the R value.

As you can see from the above description, this is much like the behavior of an object, and we can create a structured data type and then define how the method interacts with the data. The simple examples above do not show all object-oriented features, such as inheritance and polymorphism. It is necessary to note that go can not only define a method on a struct, but also on any named type. For example, you can define a new type named counter, which is an alias of type int, and then define the method on the counter type. See for example: http://play.golang.org/p/LGB-2j707c

Inheritance and polymorphism

There are several ways to define relationships between objects, and there are some differences between them, but the purpose is the same: reuse code.

    • Single Inheritance (inheritance)
    • Multiple inheritance (multiple inheritance)
    • Polymorphic (subtyping/polymorphism)
    • Object Combination (Composition)

Inheritance: An object is based on another object, using its implementation. There are two different implementations of inheritance: single-inheritance and multiple-inheritance. They differ in whether an object inherits from an object or multiple objects. A single-inheritance relationship is a tree, and a multi-inheritance relationship is a lattice structure. Single-inheritance languages include PHP, C #, Java, Ruby, and many more inherited languages including Perl, Python, C + +, etc.

Polymorphic

Polymorphism is the relationship of is-a, and inheritance is the reuse of implementation. Polymorphism defines the semantic relationships of two objects, and inheritance defines the grammatical relationships of two objects.

Object combinations

An object combination is an object that contains other objects, not inheritance, which is a has-a relationship, not a is-a.

The inheritance of the Go language

Go is intentionally designed to have no inheritance syntax. This does not mean that there is no relationship between objects in Go (struct value), except that the author of Go chooses another mechanism to imply this feature. In fact, this design of Go is a very good solution, which solves the old problems and controversies surrounding the succession of decades.

Better not inherit.

This is illustrated by an article in the following section, entitled "Why Extends Is evil", from Javaworld.

The Gang of four Design Patterns book discusses at length replacing implementation inheritance (extends) with interface in Heritance (implements).

I once attended a Java user Group meeting where James Gosling (Java's inventor) was the featured speaker. During the memorable q&a session, someone asked him: "If you could does Java over again, what would?" "I ' d leave out classes," he replied. After the laughter died down, he explained that the real problem wasn ' t classes per se, but rather implementation inherita NCE (the extends relationship). Interface Inheritance (the implements relationship) is preferable. You should avoid implementation inheritance whenever possible.

Polymorphism and combination in the Go language

The go language strictly adheres to the composition over inheritance principle principle. Go implements inheritance relationships by using combinations and polymorphism on structs and interface.
The relationship between person and address is a good example of this implementation: HTTP://PLAY.GOLANG.ORG/P/LIGPIVT2MF.

type Person struct {   Name string   Address Address}type Address struct {   Number string   Street string   City   string   State  string   Zip    string}func (p *Person) Talk() {    fmt.Println("Hi, my name is", p.Name)}func (p *Person) Location() {    fmt.Println("I’m at", p.Address.Number, p.Address.Street, p.Address.City, p.Address.State, p.Address.Zip)}func main() {    p := Person{        Name: "Steve",        Address: Address{            Number: "13",            Street: "Main",            City:   "Gotham",            State:  "NY",            Zip:    "01313",        },    }    p.Talk()    p.Location()}

Output

Hi, my name is Steve
I ' m at + Main Gotham NY 01313

The above example should be noted that the address is still a different object, except that it exists in the person.

Pseudo polymorphism in Go

AUTHORS Note:
In the first version of this post it made the incorrect claim that Go supports the is-a relationship via Anonymous fields. In reality Anonymous fields appear to be a is-a relationship by exposing embedded methods and properties as if they exis Ted on the outer struct. This falls short of being a is-a relationship for reasons now provided below. Go does has support for is-a relationships via interfaces, covered below. The current version of this post refers to Anonymous fields as a pseudo is-a relationship because it looks and behaves in Some ways like subtyping, but isn ' t.

We extend the above example to illustrate pseudo polymorphism in go. Note that the word "pseudo" here actually means that go is not a polymorphic concept, except that pseudo-polymorphism behaves like polymorphism. In the following example, a person can talk, a citizen is also a man, so he can talk. In the example above, add the following, complete code see: Http://play.golang.org/p/eCEpLkQPR3.

type Citizen struct {   Country string   Person}func (c *Citizen) Nationality() {    fmt.Println(c.Name, "is a citizen of", c.Country)}func main() {    c := Citizen{}    c.Name = "Steve"    c.Country = "America"    c.Talk()    c.Nationality()}

The above example implements the Is-a relationship by introducing an anonymous domain (person). The person is an anonymous domain (anonymous field) for citizen, and the anonymous field gives only the object type, not the name of the type. With an anonymous domain, citizen can access all the attributes (domains) and methods in the person.

Anonymous Domain method elevation

In the example above, citizen can execute the same talk () method as the person. But what if you want citizen's talk () to show a different behavior? We just need to define the method talk () on the citizen. When calling C. Talk () is called Citizen's talk () method rather than the person's talk () method, http://play.golang.org/p/jafbVPv5H9.

func (c *Citizen) Talk() {    fmt.Println("Hello, my name is", c.Name, "and I'm from", c.Country)}

Output

Hello, my name is Steve and I ' m from America
Steve is a citizen of America

Why anonymous domains are not suitable for polymorphic implementations

There are two reasons:
1. Anonymous domains can still be accessed as if they were embedded objects.
This is not a bad thing, the problem with multiple inheritance is that when multiple parent classes have the same method, there is ambiguity. However, the go language can access embedded anonymous objects by accessing properties with the same name as the anonymous type. In fact, when using an anonymous domain, go creates an object with the same name as the anonymous type. In the above example, modifying the Main method is as follows, which we can clearly see:

func main() {//    c := Citizen{}    c.Name = "Steve"    c.Country = "America"    c.Talk()         // <- Notice both are accessible    c.Person.Talk()  // <- Notice both are accessible    c.Nationality()}

Output

Hello, my name is Steve and I ' m from America
Hi, my name is Steve
Steve is a citizen of America

    1. True polymorphism, a derived object is a parent object
      If an anonymous object can be polymorphic, then the outer object should be identical to the embedded object, which is not, in fact, still a different existence. The following example confirms this point:
package maintype A struct{}type B struct {    A  //B is-a A}func save(A) {    //do something}func main() {    b := B    save(&b);  //OOOPS! b IS NOT A}

Output:

Prog.go:17:cannot use B (Type *b) as type A in function argument
[Process exited with Non-zero status]

True multi-state implementation in Go

GO interfaces is pretty unique in how to they work. This section focuses only on how they pertain to subtyping which would not do them proper justice. See the further reading sections at the end of the post to learn more.

As we mentioned above, polymorphism is a is-a relationship. In the Go language, each type is different, one type cannot be exactly the same as another, but they can be bound to the same interface (interface). Interfaces can be used in the input and output of functions (methods), thus establishing a is-a relationship between types.

The go language defines an interface that does not use the Using keyword, but is implemented by defining methods on the object. In effective go, the relationship is like "if something can do it, apply it here" (no matter the black cat, the White cat, as long as you can catch a mouse, I have this cat). This is important because it allows a type that is defined outside the package to implement that interface as well.

We proceed to the above example, add a new function Speakto, and then modify the main function to apply the method to citizen and person, Http://play.golang.org/p/lvEjaMQ25D.

func SpeakTo(p *Person) {    p.Talk()}func main() {    p := Person{Name: "Dave"}    c := Citizen{Person: Person{Name: "Steve"}, Country: "America"}    SpeakTo(&p)    SpeakTo(&c)}

Output

Running it would result in
Prog.go:48:cannot use C (type *citizen) as type *person in function argument
[Process exited with Non-zero status]

As expected, the compilation failed. Citizen are not person types, although they have the same attributes. However, we define an interface (interface) Human, and then use this interface as the input parameter of the Speakto function, the above example can run normally, http://play.golang.org/p/ifcP2mAOnf.

type Human interface {    Talk()}func SpeakTo(h Human) {    h.Talk()}func main() {    p := Person{Name: "Dave"}    c := Citizen{Person: Person{Name: "Steve"}, Country: "America"}    SpeakTo(&p)    SpeakTo(&c)}

Output

Hi, my name is Dave
Hi, my name is Steve

There are two points to note about polymorphism in the go language.
1. You can bind an anonymous domain to an interface or to multiple interfaces. Interface is used with anonymous domains and can play the same effect as polymorphism.
2. Go provides polymorphic capabilities. The use of interfaces enables different objects that implement the interface to function as input parameters, even as return results, but they still maintain their own type. As can be seen from the above example, we cannot set the name value directly when initializing the Citizen object, because name is not a property of citizen, but is a property of person, so the name value cannot be set when the citizen is initialized.

Go, an object-oriented language without object and inheritance

As mentioned above, the basic concept of object-oriented is well implemented in go, although there are differences in terminology. Go takes a struct as a combination of data and logic. By combining (composition), has-a relationships are minimized for code reuse, and inheritance defects are avoided. Go uses an interface (interface) to establish a is-a relationship between types (type).

Welcome to the world of OO programming models without objects!

Discuss

Join the discussion on Hacker News and Reddit-golang

Deep reading

http://nathany.com/good/
Http://www.artima.com/lejava/articles/designprinciples.html
Http://www.goinggo.net/2014/05/methods-interfaces-and-embedded-types.html

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.