O que viola a função opcional no protocolo?
sobes.tech IA
Resposta da IA
Adicionar requisitos ao protocolo após outros módulos ou bibliotecas já terem começado a usá-lo. Se o protocolo já foi aceite e implementado, adicionar métodos ou propriedades opcionais (não obrigatórios) causará erros de compilação em todos os locais onde o protocolo é utilizado, até que esses novos requisitos sejam cumpridos.
Requisitos opcionais permitem expandir os protocolos sem "quebrar" as implementações existentes. Classes ou estruturas podem implementar apenas parte dos métodos opcionais. Isto é útil ao trabalhar com delegados ou ao adicionar novas funções a uma API já estabelecida.
Exemplo de requisito opcional em um protocolo em Objective-C (pois Swift não suporta @optional sem @objc) :
// Em Swift, `@optional` é usado com `@objc protocol`
import Foundation
@objc protocol MyDelegate {
func requiredMethod() -> Bool
@optional func optionalMethod1()
@optional func optionalMethod2(value: Int)
}
class MyClass {
weak var delegate: MyDelegate?
func doSomething() {
if delegate?.requiredMethod() == true {
// Chamada de método opcional com verificação
delegate?.optionalMethod1?()
if let delegate = delegate {
if delegate.responds(to: #selector(delegate.optionalMethod2(value:))) {
delegate.optionalMethod2?(value: 10)
}
}
}
}
}
Em Swift, protocolos puros (sem @objc) não suportam @optional. Para ter requisitos opcionais, o protocolo deve ser marcado como @objc. Implementações desses protocolos podem usar extensões para adicionar implementações padrão de métodos opcionais, o que é uma abordagem mais moderna em Swift.
Exemplo de comportamento opcional através de extensões de protocolos em Swift:
// Abordagem mais Swift: extensões de protocolos com implementação padrão
protocol MyProtocol {
func requiredMethod() -> Bool
func optionalMethod1()
func optionalMethod2(value: Int)
}
// Fornecendo implementações padrão para métodos "opcionais"
extension MyProtocol {
func optionalMethod1() {
// Implementação padrão vazia ou comportamento padrão
print("Implementação padrão do método opcional 1")
}
func optionalMethod2(value: Int) {
// Implementação padrão vazia
print("Implementação padrão do método opcional 2 com valor: \(value)")
}
}
class MyClassSwift {
var delegate: MyProtocol?
func doSomething() {
if delegate?.requiredMethod() == true {
// Chamando métodos sem verificação de nil, pois
// eles são ou implementados na classe/estrutura, ou usam
// a implementação da extensão
delegate?.optionalMethod1()
delegate?.optionalMethod2(value: 20)
}
}
}
class MyCustomDelegate: MyProtocol {
func requiredMethod() -> Bool {
print("Método obrigatório implementado")
return true
}
// optionalMethod1() e optionalMethod2(value:) não são obrigatórios de implementar,
// será usada a implementação padrão da extensão.
// Mas podem ser sobrescritos, se desejar outro comportamento:
// func optionalMethod1() {
// print("Implementação personalizada do método opcional 1")
// }
}
let customDelegate = MyCustomDelegate()
let myClassSwift = MyClassSwift()
myClassSwift.delegate = customDelegate
myClassSwift.doSomething()
Dessa forma, adicionar uma função opcional em um protocolo viola a compatibilidade retroativa ao tentar adicionar uma nova exigência obrigatória a um protocolo já em uso na base de código. O uso de requisitos opcionais (via @objc ou, preferencialmente, via extensões de protocolos) previne essa violação.