Você acha que “a implementação de interface auto” seria útil em .NET / C # [fechado]
-
19-08-2019 - |
Pergunta
Considere o seguinte:
public class interface Person : IPerson
{
int ID { get; protected set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get { return FirstName + " " + LastName; } }
}
E esta:
public class StubPerson : IPerson
{
int ID { get { return 0; protected set { } }
string FirstName { get { return "Test" } set { } }
string LastName { get { return "User" } set { } }
string FullName { get { return FirstName + " " + LastName; } }
}
Uso:
IPerson iperson = new Person();
Ou:
IPerson ipersonStub = new StubPerson();
Ou:
IPerson ipersonMock = mocks.CreateMock<IPerson>();
Então, na verdade estamos declarando o IPerson interface e o Person classe, ao mesmo tempo:
public class interface Person : IPerson
Você acha que seria útil ter este tipo de apoio em .NET / C #?
Editar:
Devido à confusão em massa Acho que preciso para esclarecer a finalidade proposta:
Sem este recurso você teria que escrever:
interface IPerson
{
int ID { get; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get; }
}
, bem como o seguinte:
public class Person : IPerson
{
int ID { get; protected set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get { return FirstName + " " + LastName; } }
}
Não estou propondo qualquer alteração semântica em tudo.
Solução
Eu considerei o mesmo tipo de coisa um tempo atrás, especialmente para uso no caso em que você só tem uma implementação de produção de uma interface, mas você quer zombar-lo para o teste. No momento em que ele acaba sendo um pouco como o .c arquivos / .h de outrora.
Eu suspeito que, no final, que os benefícios de que são compensados ??pela complexidade extra tanto na linguagem e, em seguida, ler o código depois. Eu ainda estaria interessado em vê-lo explorado mais profundamente embora. Mesmo assim, há outras coisas muito maior na minha lista de prioridades - melhor suporte para imutabilidade estar no topo:)
Outras dicas
Deixe-me ver se eu entendo o que você está perguntando:
Por que não podemos declarar uma interface:
interface IPerson
{
string Name {get;set;}
int ID {get;set;}
}
e classes que implementam essa interface vai herdar suas propriedades sem ter que re-declará-los:
class Person : IPerson { }
//person now has properties Name and ID
A razão que você não pode fazer isso é mesmo que o texto do seu código de interface e seu código de classe são muito semelhantes, eles significa muito coisas diferentes. A interface simplesmente diz "implementador terá um nome de string com getter e setter". É a classe que diz "voltar campo privado quando getter para o nome é invocado." Mesmo se você usar o atalho de auto-propriedade para permitir que o compilador implementar essa lógica, ainda é lógica , que pertence à classe. Só porque:
string Name {get;set;}
aparência o mesmo em uma interface e em uma classe, isso não significa que, mesmo remotamente, a mesma coisa.
Seria muito perigoso para o compilador para implementar a lógica arbitrária para cumprir seus contratos para você, em vez de reclamar em tempo de compilação que você não implementaram-los. Ele poderia introduzir erros muito difícil de rastrear. Tendo compiladores cair de volta para o comportamento padrão quando nenhum comportamento é definido é um muito, muito má ideia.
Eu acredito Eiffel faz algo parecido com isso em .NET, a fim de apoiar a herança múltipla. A declaração de classe produz automaticamente uma interface correspondente. Quando o tipo de classe é referido, o compilador emite principalmente uma referência para o tipo de interface em vez disso. A principal exceção é em expressões construtor de curso.
Bem, eu acho que as outras respostas vão ajudar você a entender o uso da interface com a lógica resumo em classes concretas diferentes, eu também acho que você pode fazer algo semelhante ao que você quer usar as ferramentas de refatoração incorporadas VS.
Defina a sua classe ...
public class Person
{
public int ID { get; protected set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string FullName { get { return FirstName + " " + LastName; } }
}
Em seguida, clique direito, selecione Refactor -.> Extract Interface
Isto irá criar um arquivo separado contendo a interface para a definição da classe, você poderia, então, moldar a interface e implementação de classes em conformidade.
Extraído Interface:
interface IPerson
{
string FirstName { get; set; }
string FullName { get; }
int ID { get; }
string LastName { get; set; }
}
Eu acho que estou perdendo o ponto - o que você está realizando através da mistura de uma classe e uma interface juntos? Que problema você está resolvendo com esta abordagem?
Este:
IPerson iperson = new Person();
já é legal em C #.
Editar: Para esclarecimento - o código acima é legal dado o seguinte:
interface IPerson { }
class Person : IPerson { }
eu tinha, pelo menos, como o Visual Studio para implementar minhas propriedades de uma interface como propriedades auto se eu pedi-lo a fazê-lo.
Infelizmente, esta opção não faz e eu tenho que lidar com tocos de exceção não implementado
Não, porque você seria forçado a expor todos os membros públicos de uma interface. Tente ReSharper , e nunca se preocupar com isso novamente.
ReSharper pode fornecer essa funcionalidade, por exemplo.,
- Você pode escrever sua classe Person em primeiro lugar.
- Você pode extrair sua interface por puxando membros até ao IPerson interface.
Por isso você pode ter Visual Studio auto-gerar topos de implementação para você.
Atualizar
De qualquer forma, vamos expor sobre interfaces de primeira, citando o código fornecido na sua pergunta:
public class interface Person : IPerson
{
int ID { get; protected set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get { return FirstName + " " + LastName; } }
}
Você tem que entender que uma interface não é uma classe abstrata. Uma interface é simplesmente um contrato , um modelo do tipo, o que significa que ele vai dizer um objeto o que esperar em um outro objeto sem realmente cuidar sobre como ele é implementado.
Uma classe abstrata, por outro lado, podem conter trechos de funcionalidades que podem ser herdadas e substituídas.
No caso acima, o "interface" é inválido porque:
- você não poderia declarar restrições de escopo em interfaces (público, privado, protegido, interna) como que é um detalhe de implementação
- você não poderia declarar uma implementação padrão (por exemplo, sua propriedade
FullName
) porque mais uma vez, que é um detalhe de implementação
Parece-me o que você realmente quer é uma classe abstrata, por exemplo.,
public abstract class BasePerson
{
public abstract int ID { get; protected set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual string FullName { get { return FirstName + " " + LastName; } }
}
Eu estou apenas supondo, mas talvez isso é o que você realmente precisa.
UPDATE 2
Ok, eu acho que estou ficando com o que você quer que aconteça, então o que você quer é ser capaz de escrever isto:
public interface IPerson
{
int ID { get; set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get; }
}
E, em seguida, para a sua implementação só precisa escrever o seguinte:
public class Person : IPerson
{
public int ID { get; protected set; }
public string FullName { get { return FirstName + " " + LastName; } }
}
Sem a necessidade de especificar as propriedades nome e sobrenome.
O primeiro problema que temos de enfrentar é o fato de que as interfaces não permitem delimitadores de acesso na sua implementação:. O que aconteceria é que as propriedades herdaria o delimitador de acesso padrão, que é privado
O segundo é o fato de que enquanto nos nossos olhos string FirstName { get; set; }
em uma interface e public string FirstName { get; set; }
em uma classe são os mesmos, eles não são realmente:
- em uma interface, a definição de propriedade indicará que as assinaturas de método para os métodos getter e / ou setter estará disponível para todas as classes que implementam essa interface.
- em uma classe, a definição de propriedade irá instruir o CLR para criar um objeto anônimo que vai conter o valor da referida propriedade.
sutil diferença para o programador, a mundos de distância para o compilador.
Por fim, quando você especificar que você está implementando uma interface, Visual Studio faz fazer mágica synctactic que faz automaticamente esses topos de propriedade para você.
Eu acho que a melhor abstração para este é um traço, ou, como eu descrevi aqui , um papel. Isto é como uma interface com o código. Seu exemplo poderia ser codificado como este:
public role RPerson {
int ID { get; protected set; }
string FirstName { get; set; }
string LastName { get; set; }
string FullName { get { return FirstName + " " + LastName; } }
}
public class Person : RPerson { }
public class StubPerson : RPerson {
int ID { get { return 0; protected set { } }
string FirstName { get { return "Test" } set { } }
string LastName { get { return "User" } set { } }
string FullName { get { return FirstName + " " + LastName; } }
}
// ...
RPerson rperson = new Person();
RPerson rpersonStub = new StubPerson();