Algo que eu realmente não tinha pensado antes (sintaxe AS3):
private var m_obj:Object;
protected function get obj():Object
{
return m_obj;
}
private var m_str:String;
protected function get str():String
{
return m_str;
}
Pelo menos as subclasses não poderão definir m_obj ou m_str (embora ainda possam modificar m_obj).
Minha pergunta: isso é apenas um exagero flagrante?
A pergunta deste programador: quando ou por que alguém deve usar getters / setters para propriedades de classe em vez de simplesmente torná-los propriedades públicas? foi sugerido como duplicado.
Essa pergunta é diferente porque aborda apenas propriedades públicas versus privadas e se uma propriedade deve ser agrupada com getters e setters. Para minha pergunta, estou focando nas variáveis protegidas e em como as classes herdadas interagem com essas variáveis.
Portanto, a implementação alternativa seria:
protected var m_obj:Object; //more accessible than a private variable with a protected getter
protected var m_str:String; //more accessible than a private variable with a protected getter
Minha pergunta é semelhante, porque estou falando sobre o uso de getters protegidos triviais para impedir que subclasses gravem nas variáveis, mas para permitir a todos os outros acessos.
Em idiomas como o AS3, isso permitirá que eles façam alterações em variáveis de objeto mutáveis, desde que as próprias referências não sejam modificadas.
fonte
Respostas:
Muitas vezes é, às vezes não é.
Manter
m_obj
um bom estado conhecido ajuda a proteger o Princípio de Substituição de Liskov, mantendo seu código mais resiliente e com maior qualidade. Às vezes, você pode confiar nos herdeiros para respeitar esse comportamento, às vezes não (devido ao padrão de uso ou à sutileza do contrato que implementa). Embora esse código / pergunta também tropeçar em alguns dos motivos de "Por que o Código Limpo está sugerindo evitar variáveis protegidas?"fonte
Os getters protegidos com trivialidade têm pelo menos duas vantagens práticas sobre uma variável exposta:
Para depuração, eles são um lugar perfeito para colocar um ponto de interrupção condicional que é acionado quando "esse valor engraçado entra no seu programa". É muito mais difícil obter o mesmo controle se você acessar o valor diretamente.
Para zombar de um objeto, se você estiver usando esse método para testar descendentes.
O custo do uso de getters é praticamente zero, portanto, não há motivo real para não usá-los. Existe?
fonte
public
ouprotected
do getter! :-)get x() ... { return _y; }
ninguém jamais digitaria isso, mas isso pode acontecer devido a um recorte e colar incorreto.Não importa se você usa getters ou acesso ao campo, qualquer revisor experiente descobrirá o problema em seu design e reclamará que seus objetos expõem dados em vez de comportamento.
Observe que apelar para "protegido" não ajudará, porque o objetivo da herança é permitir que as subclasses ajustem / sintonizem o comportamento do pai ( LSP ), para não justificar a troca indiscriminada de dados com os pais. Como Bertrand Meyer coloca,
O raciocínio "Getters are evil" se aplica independentemente de você soletrar
get
explicitamente ou mascará-lo atrás do acesso ao campo.Se você estiver seriamente preocupado com o problema, a primeira coisa a considerar é o redesenho do código para livrar-se dos getters e do acesso não particular ao campo , em vez de jogar jogos mentais infrutíferos escolhendo qual caminho é menos inapropriado .
Vale ressaltar mais uma vez, ocultar o design problemático por trás da cortina de fumaça "protegida" não fará com que o problema desapareça - a herança não justifica truques como esse. Parafraseando sua pergunta, esforce-se para projetar as coisas de uma maneira que evite que as classes herdadas interajam com essas variáveis - nem por getters nem por acesso a campo. Diga, não pergunte :
Gastar tempo e esforço para decidir qual caminho preferir obter informações, contra o princípio clássico de evitar isso, agora isso me parece um exagero flagrante .
fonte
No caso de uma implementação de classe imutável, proteger suas variáveis internas violaria o contrato que você definiu; nesse caso, os getters protegidos não seriam um exagero e serão necessários (embora você precise devolver cópias de sua variável, não um ponteiro para ela). )
Nas classes mutáveis, ainda prefiro getters / setters a conceder acesso direto às minhas variáveis internas. Isso garante que você possa alterar a maneira como lida com suas variáveis internas como desejar, sem medo de quebrar nenhum código de cliente. Por exemplo, imagine que você tenha uma classe Java da seguinte maneira:
A extensão da classe cliente acessaria
SomeClass
diretamentesomeVariable
, manipulando-a como bem entenderem. Agora, isso pode criar todos os tipos de problemas se essas classes não saíremsomeVariable
em um estado aceitável. Além disso, se você decidir, em um release subsequente, alterar a definição deSomeClass
usar a emList<Integers>
vez de uma matriz, você quebrará a compatibilidade com a base de código existente, que esperaSomeClass
ter uma matriz interna deint
s, não uma lista deint
s.O uso de getters protegidos nesse caso permitiria fazer essa alteração sem quebrar nenhum contrato pré-estabelecido.
fonte