Por exemplo, suponha que eu queira uma ICar
interface e que todas as implementações contenham o campo Year
. Isso significa que toda implementação deve declarar separadamente Year
? Não seria melhor simplesmente definir isso na interface?
223
Respostas:
Embora muitas das outras respostas estejam corretas no nível semântico, acho interessante também abordar esses tipos de perguntas a partir do nível de detalhes da implementação.
Uma interface pode ser pensada como uma coleção de slots , que contêm métodos . Quando uma classe implementa uma interface, a classe é obrigada a informar ao tempo de execução como preencher todos os slots necessários. Quando voce diz
a classe diz "quando você criar uma instância minha, coloque uma referência ao Foo.M no slot do IFoo.M.
Então, quando você faz uma chamada:
o compilador gera código que diz "pergunte ao objeto qual método está no slot para IFoo.M e chame esse método.
Se uma interface é uma coleção de slots que contêm métodos, alguns desses slots também podem conter os métodos get e set de uma propriedade, os métodos get e set de um indexador e os métodos add e remove de um evento. Mas um campo não é um método . Não há "slot" associado a um campo que você pode "preencher" com uma referência ao local do campo. E, portanto, as interfaces podem definir métodos, propriedades, indexadores e eventos, mas não campos.
fonte
An interface cannot contain constants, fields, operators
Do. msdn.microsoft.com/en-us/library/ms173156.aspx )int One()
, a implementaçãopublic int One(){return 1;}
não é um campo.As interfaces em C # destinam-se a definir o contrato ao qual uma classe cumprirá - e não uma implementação específica.
Nesse sentido, as interfaces C # permitem definir propriedades - para as quais o responsável pela chamada deve fornecer uma implementação:
As classes de implementação podem usar propriedades automáticas para simplificar a implementação, se não houver uma lógica especial associada à propriedade:
fonte
Year
?public int Year => 123;
. No entanto, neste caso, não faz sentido ter um setter, portanto a interface teria que ser definida comint Year { get; }
Declare-o como uma propriedade:
fonte
Eric Lippert acertou em cheio, vou usar uma maneira diferente de dizer o que ele disse. Todos os membros de uma interface são virtuais e todos precisam ser substituídos por uma classe que herda a interface. Você não escreve explicitamente a palavra-chave virtual na declaração da interface, nem usa a palavra-chave override na classe, elas estão implícitas.
A palavra-chave virtual é implementada no .NET com métodos e a chamada v-table, uma matriz de ponteiros de método. A palavra-chave override preenche o slot da tabela v com um ponteiro de método diferente, substituindo o produzido pela classe base. Propriedades, eventos e indexadores são implementados como métodos sob o capô. Mas os campos não são. As interfaces não podem, portanto, conter campos.
fonte
Por que não apenas ter uma
Year
propriedade, o que é perfeitamente bom?As interfaces não contêm campos porque os campos representam uma implementação específica da representação de dados e a exposição deles quebraria o encapsulamento. Assim, ter uma interface com um campo seria efetivamente codificar para uma implementação em vez de uma interface, o que é um curioso paradoxo para uma interface!
Por exemplo, parte de sua
Year
especificação pode exigir que seja inválido para osICar
implementadores permitir a atribuição a um períodoYear
posterior ao ano atual + 1 ou antes de 1900. Não há como dizer que se você tivesse expostoYear
campos - é muito melhor usar propriedades em vez de fazer o trabalho aqui.fonte
A resposta curta é sim, todo tipo de implementação precisará criar sua própria variável de suporte. Isso ocorre porque uma interface é análoga a um contrato. Tudo o que você pode fazer é especificar partes específicas de código acessíveis ao público que um tipo de implementação deve disponibilizar; não pode conter nenhum código em si.
Considere este cenário usando o que você sugere:
Temos alguns problemas aqui:
myBackingVariable
vaiMyClass
usar?A abordagem mais comum adotada é declarar a interface e uma classe abstrata de barebones que a implementa. Isso permite a flexibilidade de herdar da classe abstrata e obter a implementação de graça, ou implementar explicitamente a interface e ter permissão para herdar de outra classe. Funciona mais ou menos assim:
fonte
Outros deram o 'Por que', então apenas acrescentarei que sua interface pode definir um Controle; se você o envolver em uma propriedade:
fonte
As interfaces não contêm nenhuma implementação.
fonte
Muito já foi dito, mas para simplificar, aqui está minha opinião. As interfaces destinam-se a ter contratos de método a serem implementados pelos consumidores ou classes e não a ter campos para armazenar valores.
Você pode argumentar que, então, por que propriedades são permitidas? Portanto, a resposta simples é - as propriedades são definidas internamente como apenas métodos.
fonte
Para isso, você pode ter uma classe base Car que implementa o campo year e todas as outras implementações podem herdar dele.
fonte
Uma interface define propriedades e métodos de instância pública . Os campos geralmente são privados ou, no máximo, protegidos, internos ou internos protegidos (o termo "campo" geralmente não é usado para nada público).
Conforme declarado por outras respostas, você pode definir uma classe base e definir uma propriedade protegida que será acessível por todos os herdeiros.
Uma peculiaridade é que uma interface pode de fato ser definida como interna, mas limita a utilidade da interface e é normalmente usada para definir a funcionalidade interna que não é usada por outro código externo.
fonte