DEV Community

Rodrigo Sicarelli
Rodrigo Sicarelli

Posted on

Kotlin Koans BR: Argumentos padrão

🔗 Tarefa

Imagine que você tenha várias sobrecargas de foo() na sua linguagem favorita.

Você pode substituir todas essas sobrecargas por uma única função em Kotlin.

Altere a declaração da função foo de forma que o código que usa foo seja compilado.

Java

class SobrecargaJava {
    public String foo(String name, int number, boolean toUpperCase) {
        return (toUpperCase ? name.toUpperCase() : name) + number;
    }

    public String foo(String name, int number) {
        return foo(name, number, false);
    }

    public String foo(String name, boolean toUpperCase) {
        return foo(name, 42, toUpperCase);
    }

    public String foo(String name) {
        return foo(name, 42);
    }
}
Enter fullscreen mode Exit fullscreen mode

C#

using System;

class SobrecargaCSharp
{
    public string Foo(string name, int number, bool toUpperCase)
    {
        return (toUpperCase ? name.ToUpper() : name) + number;
    }

    public string Foo(string name, int number)
    {
        return Foo(name, number, false);
    }

    public string Foo(string name, bool toUpperCase)
    {
        return Foo(name, 42, toUpperCase);
    }

    public string Foo(string name)
    {
        return Foo(name, 42);
    }
}
Enter fullscreen mode Exit fullscreen mode

Dart

class SobrecargaDart {
  String foo(String name, int number, bool toUpperCase) {
    return (toUpperCase ? name.toUpperCase() : name) + number.toString();
  }

  String foo(String name, int number) {
    return foo(name, number, false);
  }

  String foo(String name, bool toUpperCase) {
    return foo(name, 42, toUpperCase);
  }

  String foo(String name) {
    return foo(name, 42);
  }
}
Enter fullscreen mode Exit fullscreen mode

Go

package main

import (
    "fmt"
    "strings"
)

type SobrecargaGo struct{}

func (s SobrecargaGo) Foo(name string, number int, toUpperCase bool) string {
    if toUpperCase {
        return strings.ToUpper(name) + fmt.Sprintf("%d", number)
    }
    return name + fmt.Sprintf("%d", number)
}

func (s SobrecargaGo) FooWithNumber(name string, number int) string {
    return s.Foo(name, number, false)
}

func (s SobrecargaGo) FooWithUpperCase(name string, toUpperCase bool) string {
    return s.Foo(name, 42, toUpperCase)
}

func (s SobrecargaGo) FooWithName(name string) string {
    return s.Foo(name, 42, false)
}
Enter fullscreen mode Exit fullscreen mode

JavaScript

class SobrecargaJavaScript {
    foo(name, number, toUpperCase) {
        return (toUpperCase ? name.toUpperCase() : name) + number;
    }

    fooWithNameAndNumber(name, number) {
        return this.foo(name, number, false);
    }

    fooWithNameAndUpperCase(name, toUpperCase) {
        return this.foo(name, 42, toUpperCase);
    }

    fooWithName(name) {
        return this.foo(name, 42);
    }
}
Enter fullscreen mode Exit fullscreen mode

PHP

foo($name, $number, false);
    }

    public function fooWithUpperCase($name, $toUpperCase) {
        return $this->foo($name, 42, $toUpperCase);
    }

    public function fooWithName($name) {
        return $this->foo($name, 42, false);
    }
}
Enter fullscreen mode Exit fullscreen mode

Python

class SobrecargaPython:
    def foo(self, name, number, to_upper_case):
        return (name.upper() if to_upper_case else name) + str(number)

    def foo_with_number(self, name, number):
        return self.foo(name, number, False)

    def foo_with_upper_case(self, name, to_upper_case):
        return self.foo(name, 42, to_upper_case)

    def foo_with_name(self, name):
        return self.foo(name, 42, False)
Enter fullscreen mode Exit fullscreen mode

Swift

class SobrecargaSwift {
    func foo(name: String, number: Int, toUpperCase: Bool) -> String {
        return (toUpperCase ? name.uppercased() : name) + String(number)
    }

    func foo(name: String, number: Int) -> String {
        return foo(name: name, number: number, toUpperCase: false)
    }

    func foo(name: String, toUpperCase: Bool) -> String {
        return foo(name: name, number: 42, toUpperCase: toUpperCase)
    }

    func foo(name: String) -> String {
        return foo(name: name, number: 42)
    }
}
Enter fullscreen mode Exit fullscreen mode

TypeScript

class SobrecargaTypeScript {
    foo(name: string, number: number, toUpperCase: boolean): string {
        return (toUpperCase ? name.toUpperCase() : name) + number.toString();
    }

    fooWithNumber(name: string, number: number): string {
        return this.foo(name, number, false);
    }

    fooWithUpperCase(name: string, toUpperCase: boolean): string {
        return this.foo(name, 42, toUpperCase);
    }

    fooWithName(name: string): string {
        return this.foo(name, 42);
    }
} 
Enter fullscreen mode Exit fullscreen mode

Caso de uso

Quando se fala em [default arguments (https://kotlinlang.org/docs/functions.html#default-arguments) ou argumentos padrão, está se referindo a uma característica bem prática em Kotlin.

Ela permite que alguns argumentos sejam deixados de lado quando alguém chama uma função.

Se isso acontecer, o compilador usa esses argumentos padrão no lugar dos argumentos que foram pulados.

fun calculaDesconto(preco: Double, taxaDesconto: Double = 0.05) = preco - preco * taxaDesconto

calculaDesconto(preco = 50.0)
calculaDesconto(preco = 100.0, taxaDesconto = 0.10) 
Enter fullscreen mode Exit fullscreen mode

No exemplo acima, o parâmetro taxaDesconto tem um valor padrão de 5% de desconto. Ao chamar a função calculaDesconto sem especificar a taxaDesconto, o desconto de 5% será aplicado sobre o preço.

Porém, ao passar 0.10 como argumento para o parâmetro taxaDesconto, esse será o valor utilizado, substituindo o desconto padrão de 5% para 10%.

Parâmetro x Argumento

A diferença entre parâmetro e argumento em Kotlin pode ser compreendida da seguinte forma:

  • Parâmetro: identificado dentro da definição de uma função.
  • Argumento: identificado ao invocar ou usar essa função, ou seja, fora da definição.

Imagine uma função que simula a preparação de um café:

fun prepararCafe(tipo: String) = "Preparando um café $tipo..."
Enter fullscreen mode Exit fullscreen mode

Nesta definição, tipo é considerado um parâmetro da função.

Ao solicitar a preparação de um café:

val pedido = prepararCafe("espresso")
Enter fullscreen mode Exit fullscreen mode

Neste contexto, "espresso" é um argumento passado para a função prepararCafe().

Vantagens

  • Menos sobrecargas: permite uma única função em vez de várias versões com diferentes argumentos.
  • Flexibilidade: é possível chamar a função com diferentes combinações de parâmetros, contanto que os argumentos obrigatórios sejam fornecidos.
  • Compatibilidade com Java: funções com argumentos padrão são compatíveis com código Java, atuando como sobrecargas.

Desvantagens

  • Complexidade do código: se usados em excesso, podem complicar a leitura e o entendimento do código.
  • Descarte no bytecode Java: No Java, argumentos padrão do Kotlin não são reconhecidos. Para contornar isso, é necessário usar a anotação @JvmOverloads

Top comments (0)