Eu tenho uma classe existente que interage que pode abrir, ler ou gravar em um arquivo. Preciso recuperar uma modificação de arquivo para esse fim. Tenho que adicionar um novo método.
Suponha que esta é a minha definição de classe, na qual quero adicionar um novo método.
class IO_file
{
std::string m_file_name;
public:
IO();
IO(std::string file_name);
+ time_t get_mtime(file_name);
+ OR
+ time_t get_mtime();
};
Eu tenho duas opções -
Crie um objeto vazio e depois passe o nome_do_arquivo no argumento do método para o qual desejo recuperar o tempo de modificação do arquivo.
Passe o nome do arquivo na construção do objeto e simplesmente chame a função membro que operará na variável membro.
Ambas as opções servirão ao propósito. Eu também acredito que a segunda abordagem é melhor que a primeira. Mas o que eu não entendo é como ? A primeira abordagem é um design ruim, pois não utiliza uma variável de membro? Que princípio de design orientado a objetos ele viola? Se uma função de membro não usa a variável de membro, essa função de membro deve sempre ser tornada estática?
IO("somefile.txt").get_mtime("someotherfile.txt")
. Afinal, o que isso quer dizer?Respostas:
Não.
OOP não se importa se sua função de membro usa ou não propriedades de classe ou variáveis de membro. OOP se preocupa com o polimorfismo e não com a implementação da codificação. As funções estáticas têm seus usos, mas uma função não deve ser estática simplesmente porque não depende do estado do objeto. Se esse é o seu pensamento, mas não culpe o OOP porque essa ideia não veio do OOP.
Se você não precisar se lembrar do estado de chamada para chamada, não há uma boa razão para usar o estado.
Nenhum.
Não. Esse pensamento tem a seta de implicação indo na direção errada.
Uma função estática não pode acessar o estado da instância
Se a função não precisar acessar o estado da instância, ela poderá ser estática ou não estática
Tornar a função estática aqui depende inteiramente de você. Mas fará com que pareça mais global, se você o fizer. Antes de ficar estático, considere hospedar a função em uma classe sem estado. É mais flexível.
Eu tenho aqui um exemplo OOP de uma função de membro que não usa propriedades de classe ou variáveis de membro.
A função membro (e sua classe sem estado) :
Três implementações diferentes:
Um local para armazenar a escolha da implementação:
Um exemplo de uso
Saídas:
E tudo sem se
execute()
preocupar com o estado de qualquer objeto. AStrategy
classe é realmente sem estado. Único estado está emContext
. Objetos sem estado são perfeitamente bons no OOP.Encontrei este código aqui .
fonte
get_mtime
faria mais sentido aqui como uma função autônoma ou como umastatic
função, do que como você mostrou aqui.O
mtime
arquivo de um arquivo é lido, na maioria dos sistemas, de uma chamada paralstat
ou similar e não requer um descritor de arquivo aberto; portanto, não faz sentido tê-lo como uma função membro de uma classe instanciada.fonte
static
membro.A razão pela qual a segunda opção parece instintivamente melhor (e, na IMO, é melhor) é porque sua primeira opção fornece um objeto que na verdade não representa nada.
Ao não especificar o nome do arquivo, sua classe IO_file é realmente apenas um objeto abstrato que se assemelha a um arquivo concreto. Se você está passando o nome do arquivo quando chama o método, pode também refatorar todo o método em uma função pura flutuante; não há nenhum benefício real em mantê-lo vinculado a um objeto que você precisará instanciar apenas para usá-lo. É apenas uma função; o clichê de instanciação de objeto é apenas uma etapa adicional inconveniente.
Por outro lado, uma vez que o nome do arquivo recebe os métodos que você chama nesse objeto, são mais como consultas sobre uma instância específica de uma coisa. É melhor OO porque seus objetos têm um significado real e, portanto, utilidade.
fonte
Vamos traduzir isso para C. Primeiro, nossa classe - agora é uma estrutura:
Vamos, pela simplicidade dos trechos, definir uma função construtora (ignorando os vazamentos de memória por enquanto):
A opção 2 é assim:
e usado assim:
E a opção nº 1? Bem, fica assim:
E como é usado? Essencialmente, você está pedindo para passar o lixo eletrônico como o primeiro parâmetro:
Não faz muito sentido, faz?
O sistema de objetos do C ++ o oculta, mas o objeto também é um argumento do método - um argumento implícito do ponteiro chamado
this
. É essa a opção 1 que é ruim - ela possui um argumento que não é usado por definição (argumentos que não são usados, mas que podem ser usados em substituições, estão OK). Tais argumentos não contribuem em nada, complicando a assinatura, a definição e o uso da função e confundindo os leitores do código que ficam pensando sobre o que o argumento deve fazer, por que não há problema em passar lixo para ele e se o fato de você estar ou não passar lixo /NULL
/ objeto vazio para ele é a causa do bug que eles estão tentando resolver no momento. Spoiler - não é, mas eles ainda vão perder tempo explorando essa possibilidade.O fato de o argumento lixo ser implícito pode diminuir o efeito, mas ele ainda existe e pode ser facilmente evitado com a criação do método
static
.fonte