Go Language Object Oriented Programming: Difference between revisions

From NovaOrdis Knowledge Base
Jump to navigation Jump to search
 
(204 intermediate revisions by the same user not shown)
Line 1: Line 1:
=External=
=External=
* https://go.dev/doc/faq#Is_Go_an_object-oriented_language
=Internal=
=Internal=
* [[Go_Language#Object_Oriented_Programming|Go Language]]
* [[Go_Language#Object_Oriented_Programming|Go Language]]
* [[Go Functions]]
* [[Go Functions]]
* [[Go_Interfaces#Overview|Go Interfaces]]
* [[Object-Oriented_Programming#Overview|Object-Oriented Programming]]
* [[Object-Oriented_Programming#Overview|Object-Oriented Programming]]


=Overview=
=Overview=
Go is an object oriented language, but the object orientation programming model is relatively simple, compared with other object oriented languages. It has been said about Go that is "weakly" object-oriented. Go does not use the term "[[Object-Oriented_Programming#Class|class]]". There is no <code>class</code> keyword in Go. However, Go allows associating data with methods, which what a class in other programming languages really is.  
Go is an object-oriented language, but the object orientation programming model is relatively simple, compared with other object-oriented languages. It has been said about Go that is "weakly" object-oriented. Go does not use the term "[[Object-Oriented_Programming#Class|class]]", there is no <code>class</code> keyword in the language. However, Go allows associating data with methods, which what a class in other programming languages really is.  


Go uses <code>struct</code> instead, which is the encapsulation of data and methods, so the <code>struct</code> ends being equivalent to a class. To associate data with methods, we use Go functions and we give the a '''receiver type''', which is the type that function - now becoming a method - is associated with. When calling a method on an instance of the receiver type, the standard dot notation is used.
Go provides syntax to associate an arbitrary [[Go_Language#Local_Type|local type]] with arbitrary functions, turning them into [[#Method|methods]] of that type. The local type can be a [[Go_Language#Type_Alias|type alias]], a <code>[[Go_Structs#Overview|struct]]</code> or a [[#Functions_as_Receiver_Types|function]]. In this context, "local" means a type that is defined in the same package as the function. That is why a programmer cannot add new methods to built-in types.


Go does not have inheritance, constructors or generics. Inheritance can be replaced to a certain extent by composition, embedding and interface, which support code reuse and [[Object-Oriented_Programming#Polymorphism|polymorphism]].
<span id='Structs_as_Receiver_Types'></span><span id='Structs_as_Receiver_Type'></span>The most common pattern for implementing object-orientation is to use a <code>struct</code> as data encapsulation mechanism, optionally declaring fields as [[Go_Packages#Unexported_Members|unexported]], thus preventing direct access to them from outside the package, and then associating the struct with functions, by declaring the struct type as the [[#Receiver_Type|receiver type]] for those functions. The functions become [[#Method|methods]] of the type. This construct is the closest equivalent to a class in other programming languages. The standard dot notation is then used to call a method on the instance of the receiver type.


=Methods=
Go does NOT offer inheritance, overriding and polymorphism in the language syntax the same way other OOP languages do. [[#Go_Does_Not_Have_Type_Inheritance|Type inheritance is NOT available]]. Behavior inheritance can be implemented with [[Go_Interfaces#Overview|interfaces]]. Polymorphism can be implemented with a combination of [[Go_Structs_Embedded_Fields#Overview|struct field embedding]] and [[Go_Interfaces#Overview|interfaces]].
 
=<span id='Method'></span>Methods=
{{Internal|Go_Methods#Overview|Go Methods}}
 
=Encapsulation=
 
Encapsulation in this context is giving access to private data, such as package-internal data or private struct fields, via public methods. This way, access to data is controlled.
 
Encapsulation can be implemented with [[Go_Language_Modularization#Encapsulation|package]] data and with structs, where the [[Go_Structs#Encapsulation_and_Private_Fields|"private" fields]] are declared using identifiers that start with lower cap letters, so they are not visible outside the package. Controlled access to them is given via accessor and mutator methods, or [[Go_Style#Getters_and_Setters|getters and setters]], which are functions that have been declared to use the struct as a receiver type:


Functions can be associated with a type, turning them into methods of that type, by declaring a receiver type on the function. The syntax to declare a receiver type for a method is:
<syntaxhighlight lang='go'>
<syntaxhighlight lang='go'>
func (<receiver_type_parameter_name> <receiver-type>) <function-name>(...) ... {
type Color struct {
color string
}
 
func (c *Color) Init(color string) {
c.SetColor(color)
}
 
func (c *Color) Color() string {
return (*c).color
}
 
func (c *Color) SetColor(color string) {
(*c).color = color
}
}
...
var c Color
c.Init("blue")
fmt.Println(c.Color()) // prints blue
c.SetColor("red")
fmt.Println(c.Color()) // prints red
</syntaxhighlight>
</syntaxhighlight>
The receiver instance is passed by value.
=<span id='Interface'></span>Interfaces=
{{Internal|Go_Interfaces#Internal|Go Interfaces}}
=Inheritance=


Example:
==Go Does Not Have Type Inheritance==
<syntaxhighlight lang='go'>
 
</syntaxhighlight>
Go does not have type inheritance in the same sense a fully featured object-oriented programming language has.
 
In Java or Python, a type can be at the same time other type. For example, a Dog instance is at the same type an Animal instance, where "Dog" and "Animal" are two distinct types in the type system, and "Dog" inherits "Animal". The language syntax supports this model.
 
In Go, one instance is of one type, and one type alone. The instance cannot be at the same time an ancestor type and a descendant type.


==Behavior Inheritance==


Methods can only be associated with receiver types that are defined in the same package as the method. That is why a programmer cannot add new methods to built-in types.
Go supports inheritance of behavior, by allowing interface inheritance. <font color=darkkhaki>Explain this better.</font>

Latest revision as of 02:26, 4 November 2024

External

Internal

Overview

Go is an object-oriented language, but the object orientation programming model is relatively simple, compared with other object-oriented languages. It has been said about Go that is "weakly" object-oriented. Go does not use the term "class", there is no class keyword in the language. However, Go allows associating data with methods, which what a class in other programming languages really is.

Go provides syntax to associate an arbitrary local type with arbitrary functions, turning them into methods of that type. The local type can be a type alias, a struct or a function. In this context, "local" means a type that is defined in the same package as the function. That is why a programmer cannot add new methods to built-in types.

The most common pattern for implementing object-orientation is to use a struct as data encapsulation mechanism, optionally declaring fields as unexported, thus preventing direct access to them from outside the package, and then associating the struct with functions, by declaring the struct type as the receiver type for those functions. The functions become methods of the type. This construct is the closest equivalent to a class in other programming languages. The standard dot notation is then used to call a method on the instance of the receiver type.

Go does NOT offer inheritance, overriding and polymorphism in the language syntax the same way other OOP languages do. Type inheritance is NOT available. Behavior inheritance can be implemented with interfaces. Polymorphism can be implemented with a combination of struct field embedding and interfaces.

Methods

Go Methods

Encapsulation

Encapsulation in this context is giving access to private data, such as package-internal data or private struct fields, via public methods. This way, access to data is controlled.

Encapsulation can be implemented with package data and with structs, where the "private" fields are declared using identifiers that start with lower cap letters, so they are not visible outside the package. Controlled access to them is given via accessor and mutator methods, or getters and setters, which are functions that have been declared to use the struct as a receiver type:

type Color struct {
	color string
}

func (c *Color) Init(color string) {
	c.SetColor(color)
}

func (c *Color) Color() string {
	return (*c).color
}

func (c *Color) SetColor(color string) {
	(*c).color = color
}

...

var c Color
c.Init("blue")
fmt.Println(c.Color()) // prints blue
c.SetColor("red")
fmt.Println(c.Color()) // prints red

Interfaces

Go Interfaces

Inheritance

Go Does Not Have Type Inheritance

Go does not have type inheritance in the same sense a fully featured object-oriented programming language has.

In Java or Python, a type can be at the same time other type. For example, a Dog instance is at the same type an Animal instance, where "Dog" and "Animal" are two distinct types in the type system, and "Dog" inherits "Animal". The language syntax supports this model.

In Go, one instance is of one type, and one type alone. The instance cannot be at the same time an ancestor type and a descendant type.

Behavior Inheritance

Go supports inheritance of behavior, by allowing interface inheritance. Explain this better.