31 - Métodos asociados a un struct

Un struct puede tener asociado métodos para procesar los campos del struct propiamente dicho.

Un método es una función que tiene un parámetro extra de un determinado tipo de struct que se ubica después de la palabra clave func y previo al nombre de la función.

Veremos con un ejemplo la sintaxis para la asociación de funciones a un struct determinado.

Problema 1:

Declarar un struct que permita almacenar el nombre de una persona y su edad.
Definir los métodos que permitan:
1 Cargar el nombre y la edad de persona
2 Imprimir el nombre y la edad
3 Mostrar un mensaje si es mayor de edad
En la main definir dos variables del tipo struct declarado y llamar a sus métodos

Programa: ejercicio135.go

package main

import "fmt"

type Persona struct {
    nombre string
    edad int
}

func (persona *Persona) cargar() {
    fmt.Print("Ingrese el nombre de la persona:")
    fmt.Scan(&persona.nombre)
    fmt.Print("Ingrese la edad:")
    fmt.Scan(&persona.edad)
}

func (persona Persona) imprimir() {
    fmt.Println("Nombre:", persona.nombre)
    fmt.Println("Edad:", persona.edad)
}

func (persona Persona) esMayor() {
    if persona.edad >= 19 {
        fmt.Println(persona.nombre, "es mayor de edad")
    } else {
        fmt.Println(persona.nombre, "no es mayor de edad")
    }
}


func main() {
    var persona1, persona2 Persona
    persona1.cargar()
    persona1.imprimir()
    persona1.esMayor()
    persona2.cargar()
    persona2.imprimir()
    persona2.esMayor()    
}

En la declaración del struct no hay ninguna referencia a los métodos que tiene asociado esta estructura (simplemente declaramos sus campos):

type Persona struct {
    nombre string
    edad int
}

En la declaración de los métodos si antecedemos un puntero de tipo Persona si los campos serán modificados como sucede cuando tenemos que cargarlos:

func (persona *Persona) cargar() {
    fmt.Print("Ingrese el nombre de la persona:")
    fmt.Scan(&persona.nombre)
    fmt.Print("Ingrese la edad:")
    fmt.Scan(&persona.edad)
}

Como vemos previo al nombre del método (en este caso se llama "cargar") antecedemos a que struct se asocia esta función definiendo un parámetro extra.

Dentro del método podemos acceder a este parámetro extra para modificarlo, consultarlo etc.

Desde la main donde definimos dos variables del tipo de dato Persona llamamos a los métodos antecediendo el nombre de la variable:

func main() {
    var persona1, persona2 Persona
    persona1.cargar()
    persona1.imprimir()
    persona1.esMayor()

Cuando llamamos persona1.cargar() como vemos el parámetro extra del método recibe la dirección de la variable persona1 en el parámetro persona.:

func (persona *Persona) cargar() {

Cuando llamamos al método imprimir a partir de persona1:

    persona1.imprimir()

Lo que sucede que el parámetro extra persona del método imprimir recibe una copia de la variable "persona1":

func (persona Persona) imprimir() {
    fmt.Println("Nombre:", persona.nombre)
    fmt.Println("Edad:", persona.edad)
}

Como no modificamos los campos en le método imprimir y en esMayor lo que le enviamos no es un puntero sino una copia de la variable definida en la main.

Problemas propuestos

  • Se tiene la siguiente declaración:
    type Triangulo struct {
        lado1 int
        lado2 int
        lado3 int
    }
    
    Desarrollar un programa que implemente los siguientes métodos: inicializar los campos por teclado, imprimir el valor del lado mayor y otro método que muestre si es equilátero o no.
  • Se tiene la siguiente declaración:
    type Rectangulo struct {
        int ladoMayor
        int ladoMenor
    }
    
    Definir los siguientes métodos: cargar los lados del rectángulo, retornar su perímetro y su superficie.
    Desarrollar un cuarto método que duplique las medidas de cada lado.
    En la main definir una variable de tipo Rectangulo y llamar a sus métodos.
  • Se tiene la siguiente declaración:
    type Empleado struct {
        nombre string
        sueldo float64
    }
    
    Confeccionar los métodos para la carga, otro para imprimir sus datos y por último uno que imprima un mensaje si debe pagar impuestos (si el sueldo supera a 3000)
  • Se tiene la siguiente declaración:
    type Operacion struct{
        int valor1
        int valor2
    }
    
    Implementar los métodos que permitan cargar los dos campos enteros, retornar su suma, resta, multiplicación y división.
Solución
ejercicio136.go

package main

import "fmt"

type Triangulo struct {
    lado1 int
    lado2 int
    lado3 int
}

func (tri *Triangulo) cargar() {
    fmt.Print("Ingrese primer lado del triángulo:")
    fmt.Scan(&tri.lado1)
    fmt.Print("Ingrese segundo lado del triángulo:")
    fmt.Scan(&tri.lado2)
    fmt.Print("Ingrese tercer lado del triángulo:")
    fmt.Scan(&tri.lado3)
}

func (tri Triangulo) ladoMayor() {
    if tri.lado1 > tri.lado2 && tri.lado1 > tri.lado3 {
        fmt.Println("El lado mayor es:", tri.lado1)
    } else {
        if tri.lado2 > tri.lado3 {
            fmt.Println("El lado mayor es:", tri.lado2)            
        } else {
            fmt.Println("El lado mayor es:", tri.lado3)            
        }
    }
}

func (tri Triangulo) esEquilatero() {
    if tri.lado1 == tri.lado2 && tri.lado1 == tri.lado3 {
        fmt.Println("El triángulo es equilátero")
    } else {
        fmt.Println("El triángulo no es equilátero")
    }
}

func main() {
    var triangulo1 Triangulo
    triangulo1.cargar()
    triangulo1.ladoMayor()
    triangulo1.esEquilatero()
}




ejercicio137.go

package main

import "fmt"

type Rectangulo struct {
    ladoMayor int
    ladoMenor int
}

func (rect *Rectangulo) cargar() {
    fmt.Print("Ingrese el lado menor del rectángulo:")
    fmt.Scan(&rect.ladoMenor)
    fmt.Print("Ingrese el lado mayor del rectángulo:")
    fmt.Scan(&rect.ladoMayor)
}

func (rect Rectangulo) retornarSuperficie() int {
    return rect.ladoMenor * rect.ladoMayor
}

func (rect Rectangulo) retornarPerimetro() int {
    return (rect.ladoMenor * 2) + (rect.ladoMayor * 2)
}

func (rec *Rectangulo) duplicarLados() {
    rec.ladoMenor = rec.ladoMenor * 2
    rec.ladoMayor = rec.ladoMayor * 2
}

func main () {
    var rectangulo1 Rectangulo
    rectangulo1.cargar()
    fmt.Println("La superficie del rectángulo es:", rectangulo1.retornarSuperficie())
    fmt.Println("El perímetro del rectángulo es:", rectangulo1.retornarPerimetro())
    rectangulo1.duplicarLados()
    fmt.Println("La superficie y perímetro luego de duplicar las medidas de los lados.")
    fmt.Println("La superficie del rectángulo es:", rectangulo1.retornarSuperficie())
    fmt.Println("El perímetro del rectángulo es:", rectangulo1.retornarPerimetro())    
}




ejercicio138.go

package main

import "fmt"

type Empleado struct {
    nombre string
    sueldo float64
}

func (emp *Empleado) cargar() {
    fmt.Print("Ingrrese el nombre del empleado:")
    fmt.Scan(&emp.nombre)
    fmt.Print("Ingrese el sueldo:")
    fmt.Scan(&emp.sueldo)
}

func (emp Empleado) imprimir() {
    fmt.Println(emp.nombre, "-", emp.sueldo)
}

func (emp Empleado) pagaImpuesto() {
    if emp.sueldo >3000 {
        fmt.Println(emp.nombre, "debe pagar impuesto")
    } else {
        fmt.Println(emp.nombre, "no debe pagar impuestos")
    }
}

func main() {
    var empleado1 Empleado
    empleado1.cargar()
    empleado1.imprimir()
    empleado1.pagaImpuesto()
}




ejercicio139.go

package main

import "fmt"

type Operacion struct{
    valor1 int
    valor2 int
}

func (opera *Operacion) cargar() {
    fmt.Print("Ingrese primer valor:")
    fmt.Scan(&opera.valor1)
    fmt.Print("Ingrese segundo valor:")
    fmt.Scan(&opera.valor2)
}

func (opera Operacion) sumar() int {
    return opera.valor1 + opera.valor2
}

func (opera Operacion) restar() int {
    return opera.valor1 - opera.valor2
}

func (opera Operacion) multiplicar() int {
    return opera.valor1 * opera.valor2
}

func (opera Operacion) dividir() int {
    return opera.valor1 / opera.valor2
}


func main () {
    var operacion1 Operacion
    operacion1.cargar()
    fmt.Println("La suma de los dos valores es:", operacion1.sumar())
    fmt.Println("La resta de los dos valores es:", operacion1.restar())
    fmt.Println("El producto de los dos valores es:", operacion1.multiplicar())
    fmt.Println("La división de los dos valores es:", operacion1.dividir())        
}