Home Artigos Polimorfismo em Go

Polimorfismo em Go

0
0
492

O polimorfismo em Go é alcançado com a ajuda das interfaces. Interfaces podem ser implicitamente implementadas em Go. Um tipo implementa uma interface se fornece definições para todos os métodos declarados na interface. Vamos ver como o polimorfismo é alcançado em Go com a ajuda de interfaces.

Qualquer tipo que define todos os métodos de uma interface, implicitamente, implementa essa interface.

Uma variável de tipo interface pode conter qualquer valor que implemente a interface. Esta propriedade das interfaces é usada para alcançar o polimorfismo em Go.

Vamos entender o polimorfismo em Go com a ajuda de um programa que calcula o lucro líquido de uma organização. Por simplicidade, podemos assumir que esta organização imaginária tem renda de dois tipos de projetos, isto é. faturamento fixo e tempo e material. O lucro líquido da organização é calculado pela soma dos rendimentos desses projetos. Para manter este tutorial simples, assumiremos que a moeda é o dólar e não lidaremos com centavos. Ele será representado usando int.

Vamos definir a interface Income:

[code lang=”go”] type Income interface {
calculate() int
source() string
}
[/code]

A interface Income definida acima contém dois métodos calculate () que calcula e retorna a renda do source e source (), que retorna o nome do source.

A seguir vamos definir a struct do tipo de projeto FixedBilling:

[code lang=”go”] type FixedBilling struct {
projectName string
biddedAmount int
}
[/code]

A struct FixedBilling possui dois campos: projectName que representa o nome do projeto e biddedAmount que é o valor que a organização ofereceu para o projeto.

A struct TimeAndMaterial irá representar os projetos desse tipo:

[code lang=”go”] type TimeAndMaterial struct {
projectName string
noOfHours int
hourlyRate int
}
[/code]

A struct TimeAndMaterial possui três campos: projectName, noOfHours e hourlyRate.

O próximo passo será definir métodos para esses tipos de struct que calculam e retornam a renda real e a fonte de renda:

[code lang=”go”] func (fb FixedBilling) calculate() int {
return fb.biddedAmount
}

func (fb FixedBilling) source() string {
return fb.projectName
}

func (tm TimeAndMaterial) calculate() int {
return tm.noOfHours * tm.hourlyRate
}

func (tm TimeAndMaterial) source() string {
return tm.projectName
}
[/code]

No caso dos projetos FixedBilling, o lucro é apenas o montante estimado para o projeto. Por isso, retornamos isso do método calculate () do tipo FixedBilling.

No caso dos projetos TimeAndMaterial, o rendimento é o produto do noOfHours e do hourlyRate. Esse valor é retornado do método calculate () com o tipo de receptor TimeAndMaterial.

Retornamos o nome do projeto como fonte de renda do método source ().

Uma vez que as estruturas FixedBilling e TimeAndMaterial fornecem definições para os métodos calculate () e source () da interface Income, ambas as structs implementam a interface Income.

Vamos declarar a função calculateIncome que irá calcular e imprimir a renda total:

[code lang=”go”] func calculateNetIncome(ic []Income) {
var netincome int = 0
for _, income := range ic {
fmt.Printf(“Income From %s = $%d\n”, income.source(), income.calculate())
netincome += income.calculate()
}
fmt.Printf(“Net income of organisation = $%d”, netincome)
}
[/code]

A função calculateNetIncome acima aceita um slice de interfaces Income como argumento. Ele calcula a renda total, iterando sobre o slice e chamando o método calculate () em cada um de seus itens. Ele também exibe a fonte de renda chamando o método source (). Dependendo do tipo concreto da interface Income, diferentes métodos calculate () e source () serão chamados. Assim, conseguimos o polimorfismo na função calculateNetIncome ().

No futuro se um novo tipo de fonte de renda for adicionado pela organização, esta função ainda calculará a renda total corretamente sem uma única linha de mudança de código!

A última parte faltante é a função main do programa:

[code lang=”go”] func main() {
project1 := FixedBilling{projectName: “Project 1”, biddedAmount: 5000}
project2 := FixedBilling{projectName: “Project 2”, biddedAmount: 10000}
project3 := TimeAndMaterial{projectName: “Project 3”, noOfHours: 160, hourlyRate: 25}
incomeStreams := []Income{project1, project2, project3}
calculateNetIncome(incomeStreams)
}
[/code]

Na função main acima, criamos três projetos, dois do tipo FixedBilling e um do tipo TimeAndMaterial. Em seguida, criamos um slice do tipo Income com esses 3 projetos. Uma vez que cada um desses projetos implementou a interface Income, é possível adicionar todos os três projetos a um slice do tipo Income. Finalmente, chamamos a função calculateNetIncome passando o slice de Income e a função exibirá as várias fontes de renda e as receitas delas.

Agora digamos que a organização encontrou um novo fluxo de renda através de propagandas. Vamos ver como é simples adicionar este novo fluxo de renda e calcular a renda total sem fazer alterações na função calculateNetIncome. Isso se torna possível devido ao polimorfismo.

Vamos primeiro definir o tipo Advertisement e os métodos calculate () e source () nessa struct:

[code lang=”go”] type Advertisement struct {
adName string
CPC int
noOfClicks int
}
func (a Advertisement) calculate() int {
return a.CPC * a.noOfClicks
}
func (a Advertisement) source() string {
return a.adName
}
[/code] O tipo Advertisement possui três campos adName, CPC (custo por clique) e noOfClicks (número de cliques). A receita total de anúncios é o produto de CPC e noOfClicks.

Vamos modificar a função main um pouco para incluir esse novo fluxo de renda.

[code lang=”go”] func main() {
project1 := FixedBilling{projectName: “Project 1”, biddedAmount: 5000}
project2 := FixedBilling{projectName: “Project 2”, biddedAmount: 10000}
project3 := TimeAndMaterial{projectName: “Project 3”, noOfHours: 160, hourlyRate: 25}
bannerAd := Advertisement{adName: “Banner Ad”, CPC: 2, noOfClicks: 500}
popupAd := Advertisement{adName: “Popup Ad”, CPC: 5, noOfClicks: 750}
incomeStreams := []Income{project1, project2, project3, bannerAd, popupAd}
calculateNetIncome(incomeStreams)
}
[/code]

Criamos dois anúncios chamados bannerAd e popupAd. O slice incomeStreams inclui os dois anúncios que acabamos de criar.

Você notou que não fizemos nenhuma alteração na função calculateNetIncome, embora adicionemos um novo fluxo de renda. Funciona por causa do polimorfismo. Uma vez que o novo tipo Advertisement também implementou a interface Income, conseguimos adicioná-lo ao slice incomeStreams. A função calculateNetIncome também funcionou sem alterações, pois foi capaz de chamar os métodos calculate () e source () do tipo Advertisement.

Isso nos leva ao final deste artigo. Espero que tenham gostado e que isso mostre uma base do conceito de polimorfismo em Go.

Referência: https://golangbot.com/polymorphism/

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Veja Também

Validação de CPF e CNPJ em Go

Simples e direto. Funções para validar CPF e CNPJ em Go. …