Pergunta

Como você declarar um método em C # que deve ser substituído (ou substituível) por uma classe dereived - possivelmente até mesmo fora de sua montagem? - mas que deve ser exigível apenas a partir de dentro da classe real

(i. Como uma função virtual privado em C ++)

[editar]
private virtual é exatamente o que eu pretendo: "Aqui está uma maneira de modificar o meu comportamento, mas você ainda não estão autorizados a chamar esta função diretamente (porque chamá-lo requer invocações arcanos que só minha classe base deve fazer) "

Assim, para esclarecer: o que é a melhor expressão para que em C #

Foi útil?

Solução

C # faz uma garantia forte para "private" do C ++ faz. Em C ++, você pode realmente substituir um método virtual privada. Mas isso significa que o código em uma classe base pode executar código em uma classe derivada. Quebrando a promessa de que o método privado é realmente privado e só pode ser chamado por métodos na mesma classe.

Algo que não ajuda aqui é que C ++ não requer repetindo a palavra-chave virtual. Levando até difícil de engenharia-reversa de mistérios como este:

#include "stdafx.h"
#include <iostream>

class Base {
private:
    virtual void Method() = 0;
public:
    void Test() {
        Method();
    }
};
class Derived : public Base {
private:
    void Method() { std::cout << "Who the heck called me?"; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Base* p = new Derived;
    p->Test();
}

Eu concordo que há um possível papel para a herança privada. Os linguagem designers de C # disse não! embora.

Outras dicas

Quando você diz que só deve ser exigível "dentro da classe real" quer dizer a classe base ou a classe derivada? Nenhum destes é viável por conta própria. O mais próximo é o de utilizar um método protegido, o que significa que pode ser chamado a partir da classe declarante, a classe de derivados, e qualquer outra classe derivadas.

Um membro privado não está visível para classes filhas. Acho protegida virtual irá executar a maneira que você gostaria?

UPDATE:

Aqui em maior detalhe é uma explicação sobre o que você pode fazer com a herança e funções primordiais dentro C #. Eu tentei usar um exemplo pouco significativo, mas considerá-lo entender que é um design de classe pobre e eu não sempre recomendar a implementação das classes descritas desta forma. No entanto, espero que, talvez, isso vai lhe dar uma avenida para abordar resolver o seu problema original de uma forma que poderia ser aceitável. Não há nenhuma maneira para evitar uma classe concreta de chamar qualquer um de seus membros, mas se a sua estrutura é assim de qualquer maneira, talvez não o seu problema.

public abstract class Animal
{
    public void DisplayAttributes()
    {
        Console.WriteLine(Header());
        Console.WriteLine("Name: " + Name());
        Console.WriteLine("Legs: " + Legs());
        Console.WriteLine();
    }

    protected virtual int Legs()
    {
        return 4;
    }

    private string Header()
    {
        return "Displaying Animal Attributes";
    }

    protected abstract string Name();
}

public class Bird : Animal
{
    protected override string Name()
    {
        return "Bird";
    }

    protected override int Legs()
    {
        return 2;
    }
}

public class Zebra : Animal
{
    protected override string Name()
    {
        return "Zebra";
    }
}

public class Fish : Animal
{
    protected override string Name()
    {
        return "Fish";
    }

    protected override int Legs()
    {
        return 0;
    }

    private string Header()
    {
        return "Displaying Fish Attributes";
    }

    protected virtual int Gils()
    {
        return 2;
    }

    public new void DisplayAttributes()
    {
        Console.WriteLine(Header());
        Console.WriteLine("Name: " + Name());
        Console.WriteLine("Gils: " + Gils());
        Console.WriteLine();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Bird bird = new Bird();
        bird.DisplayAttributes();
        //Displaying Animal Attributes
        //Name: Bird
        //Legs: 2

        Zebra zebra = new Zebra();
        zebra.DisplayAttributes();
        //Displaying Animal Attributes
        //Name: Zebra
        //Legs: 4


        Fish fish = new Fish();
        fish.DisplayAttributes();
        //Displaying Fish Attributes
        //Name: Fish
        //Gils: 2

        List<Animal> animalCollection = new List<Animal>();
        animalCollection.Add(bird);
        animalCollection.Add(zebra);
        animalCollection.Add(fish);

        foreach (Animal animal in animalCollection)
        {
            animal.DisplayAttributes();
            //Displaying Animal Attributes
            //Name: Bird
            //Legs: 2

            //Displaying Animal Attributes
            //Name: Zebra
            //Legs: 4

            //Displaying Animal Attributes
            //Name: Fish
            //Legs: 0
            //*Note the difference here
            //Inheritted member cannot override the
            //base class functionality of a non-virtual member
        }
    }
}

Neste exemplo, Pássaro, Zebra, e Peixe poderiam chamar seus métodos Nome e pernas, mas dentro do contexto se este exemplo, não seria necessariamente utilidade em fazê-lo. Além disso, como mostrado por peixes, os DisplayAttributes () pode ser modificado para uma instância de uma classe de derivados de betão; mas quando você está olhando para um animal, como no loop foreach, você começa a DisplayAttributes comportamento classes de base, independentemente do tipo real do animal. Espero que isso ajuda povide Maio o tipo de funcionalidade que você gostaria de replicar.

Será que você considerar o uso de um delegado para fazer isso? Você pode permitir que a classe derivada para definir o delegado via alguma propriedade protegida ou passá-la para o seu construtor. Você também pode usar como padrão o delegado para a sua implementação interna que é um método privado da sua classe base.

Aqui está um exemplo do que vboctor já mencionou:

public class Base
{
    private Func<Base, int> func;
    protected void SetFunc(Func<Base, int> func)
    {
        this.func = func;
    }

    private void CallFunc()
    {
        if (func != null)
        {
            var i = func(this);
        }
    }
}

public class Sub : Base
{
    private void DoFuncyStuff()
    {
         this.SetFunc(b => 42);
    }
}

Por que você precisa que ele seja privado? Protegido deve ser suficiente, aqui. Você está pedindo o autor subclasse para escrever código que não pode chamar. O que isso realizar? Eles poderiam usar esse código de qualquer maneira.

Como eu li a sua pergunta, você poderia significar duas coisas.

Em primeiro lugar, se se quiser que uma função na classe A que pode ser anulado em crianças Classe B, mas não é visível para qualquer classe exterior:

public class ClassA
{
  protected virtual ReturnType FunctionName(...) { ... }
}

public class ClassB
{
  protected override ReturnType FunctionName(...) { ... }
}

Em segundo lugar, se você quiser forçar uma classe de implementação para definir a função:

public abstract class ClassA
{
  protected abstract ReturnType FunctionName(...);
}

public class ClassB
{
  protected override ReturnType FunctionName(...) { ... }
}

Outro conceito que você pode olhar se você está apenas cavando em C # que está relacionado meio é classes parciais. Esta é a idéia de dois arquivos de origem de serem combinados em tempo de compilação para criar uma classe, ambos da mesma montagem:

Arquivo 1:

public partial class ClassA
{
    private ReturnType FunctionName(...);
}  

Arquivo 2:

public partial class ClassA
{
  //actual implimentation
  private ReturnType FunctionName(...){ ... }; 
}

Partials não são amplamente usados, exceto quando se lida com arquivos destinados gerado, como os arquivos Linq2Sql, ou EDM, ou WinForms, etc.

Acho que isso não vai funcionar como pretendido, mas deixe-me esboçar alguns pseudo-código para você:

public interface BaseClassFunction {
    void PleaseCallMe();
}

public class BaseClass {
    private BaseClassFunction fn;
    public BaseClass(BaseClassFunction fn) {
        this.fn = fn;
    }
    private CallMe() {
        fn.PleaseCallMe();
    }
    public PublicCallMe() {
        CallMe();
    }
}

private class DerivedClassFunction : BaseClassFunction {
    void PleaseCallMe() { ... do something important ... }
}

public class DerivedClassFunction {
    public DerivedClassFunction() : BaseClass(new DerivedClassFunction()) {
    }
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top