Abstração
Em ciência da computação, abstração é a habilidade de se concentrar nos aspectos essenciais de um contexto, ignorando características menos importantes ou acidentais. Em programação orientada a objetos, uma classe é uma abstração de entidades existentes no contexto de uma aplicação. Como exemplo, uma classe Usuario pode representar um usuário de um sistema que pode se dividir em subclasses como UsuarioAdministrador, UsuarioComum, UsuarioVisitante, etc.
Principais Conceitos
Uma classe abstrada é criada para representar entidades e conceitos abstratos. A classe abstrata é sempre uma "Super classe" que não possui instâncias, que implementa métodos que são de uso comum a todas as subclasses. As subclasses são classes que herdam os métodos e atributos da classe abstrata, podendo implementar métodos específicos.
Como funciona em Go
Em Go, não existe o conceito de classes, mas podemos alcançar a abstração por meio de interfaces. Uma interface é um tipo abstrato que define um conjunto de métodos que um tipo deve possuir. Em Go, a implementação das interfaces é implícita, o que significa que qualquer tipo que tenha os métodos exigidos por uma interface automaticamente a implementa, sem a necessidade de uma declaração explícita. Isso permite que um tipo concreto seja tratado como uma interface, sem a necessidade de conhecer a implementação específica do tipo.
package usuario
type Usuario interface {
Nome() string
Email() string
}
package usuario
// Struct que representa um usuário administrador
type UsuarioAdministrador struct {
nome string
email string
}
// Método que retorna o nome do usuário administrador
func (ua UsuarioAdministrador) Nome() string {
return ua.nome
}
// Método que retorna o email do usuário administrador
func (ua UsuarioAdministrador) Email() string {
return ua.email
}
// Função que registra um usuário administrador
func RegistraUsuarioAdministrador(nome, email string) Usuario {
return UsuarioAdministrador{nome, email}
}
package usuario
// Struct que representa um usuário comum
type UsuarioComum struct {
nome string
email string
}
// Método que retorna o nome do usuário comum
func (uc UsuarioComum) Nome() string {
return uc.nome
}
// Método que retorna o email do usuário comum
func (uc UsuarioComum) Email() string {
return uc.email
}
// Função que registra um usuário comum
func RegistraUsuarioComum(nome, email string) Usuario {
return UsuarioComum{nome, email}
}
package usuario
import "fmt"
// PrintUsuarioComum imprime os dados de um usuario
func PrintUsuario(u Usuario) {
fmt.Printf("Nome: %s, Email: %s\n", u.Nome(), u.Email())
}
package main
import "abstracao/usuario"
func main() {
// Registra um usuário comum
usuario_comum := usuario.RegistraUsuarioComum("Usuario Commum", "usuario_comum@email.com")
// Registra um usuário administrador
usuario_administrador := usuario.RegistraUsuarioAdministrador("Usuario Administrador", "usuario_administrador@email.com")
// Imprime os dados dos usuários
usuario.PrintUsuario(usuario_comum)
usuario.PrintUsuario(usuario_administrador)
}
abstracao ➜ go run main.go
Nome: Usuario Commum, Email: usuario_comum@email.com
Nome: Usuario Administrador, Email: usuario_administrador@email.com
Neste exemplo, temos uma interface Usuario
que define os métodos Nome
e Email
. As structs UsuarioAdministrador
e UsuarioComum
implementam a interface Usuario
, fornecendo suas próprias versões dos métodos Nome
e Email
. As funções RegistraUsuarioAdministrador
e RegistraUsuarioComum
são responsáveis por criar instâncias de UsuarioAdministrador
e UsuarioComum
, respectivamente. No arquivo main.go
, instanciamos objetos de UsuarioAdministrador
e UsuarioComum
, e chamamos os métodos Nome e Email de cada um para demonstrar a implementação da interface.
Conclusão
A abstração é fundamental no design de software, permitindo a definição de contratos de comportamento independentes das implementações específicas. Em Go, embora não existam classes como nas linguagens orientadas a objetos tradicionais, a abstração é alcançada eficientemente através de interfaces. Interfaces permitem a criação de tipos que aderem a um conjunto de métodos, promovendo flexibilidade e reutilização de código. Ao separar a definição de comportamento da implementação concreta, interfaces simplificam a manutenção de sistemas complexos e permitem que novos tipos possam ser integrados com facilidade, melhorando a modularidade e a extensibilidade do código.
Projeto
Referências