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.

Foi útil?

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.,

  1. Você pode escrever sua classe Person em primeiro lugar.
  2. 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(); 
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top