Pergunta

Eu não tenho certeza se isso é uma coisa estranha para fazer ou não, ou se é de alguma forma cheiro de código ... mas eu queria saber se havia uma maneira (algum tipo de padrão oop seria bom) para "cast" um tipo de base a uma forma do seu tipo derivado. Eu sei que isso não faz muito sentido como o tipo derivado terá funcionalidades adicionais que o pai não faz oferta que está em sua auto não fundamentalmente sólida. Mas há alguma maneira de fazer isso? Aqui está um exemplo de código para que eu possa explicar melhor o que I "m perguntando.

public class SomeBaseClass {
    public string GetBaseClassName {get;set;}
    public bool BooleanEvaluator {get;set;}
}

public class SomeDerivedClass : SomeBaseClass {
    public void Insert(SqlConnection connection) {
          //...random connection stuff
          cmd.Parameters["IsItTrue"].Value = this.BooleanEvalutar;
          //...
    }
}

public static void Main(object[] args) {
    SomeBaseClass baseClass = new SomeBaseClass();
    SomeDerivedClass derClass = (SomeDerivedClass)baseClass; 
    derClass.Insert(new sqlConnection());
}

Eu sei que isso parece bobo, mas existe alguma maneira de realizar algo deste tipo?

Foi útil?

Solução

Não profundamente, em "administrado" línguas. Esta é downcasting , e não há sane para baixo maneira de lidar com isso, para exatamente a razão que você descreveu (subclasses fornecer mais do que classes base - onde é que este "mais" vem?). Se você realmente quer um comportamento semelhante para uma hierarquia particular, você pode usar construtores para tipos derivados que levarão o tipo base como um protótipo.

Pode-se construir algo com reflexão que lidou com os casos simples (mais tipos específicos que não têm estado adição). Em geral, apenas redesenhar para evitar o problema.

Edit: Woops, não podem os operadores de conversão de escrita entre a base tipos / derivados. Uma singularidade da Microsoft tentar "proteger" contra si mesmo. Ah, bem, pelo menos eles não estão onde perto tão mau como dom

Outras dicas

Tente composição em vez de herança!

Parece-me que você seria melhor fora de passar uma instância de SomeBaseClass ao SomeDerivedClass (que classe base não derive, e deve ser renomeado como tal)

public class BooleanHolder{       
    public bool BooleanEvaluator {get;set;}
}

public class DatabaseInserter{
    BooleanHolder holder;

    public DatabaseInserter(BooleanHolder holder){
        this.holder = holder;
    }

    public void Insert(SqlConnection connection) {
          ...random connection stuff
          cmd.Parameters["IsItTrue"].Value = holder.BooleanEvalutar;
          ...
    }
}

public static void Main(object[] args) {
    BooleanHolder h = new BooleanHolder();
    DatabaseInserter derClass = new DatabaseInserter(h);
    derClass.Insert(new sqlConnection);
}

Confira http: //www.javaworld. com / JavaWorld / jw-11-1998 / jw-11-techniques.html (página 3):

reutilização de código através de composição Composição fornece uma forma alternativa para a Apple reutilizar implementação da Fruit descasca(). Em vez de estender Fruit, A Apple pode conter uma referência a uma Fruit exemplo e definir a sua própria casca () método que simplesmente invoca casca () sobre Fruto.

Pessoalmente, eu não acho que vale a pena o incômodo de usar Herança neste caso. Em vez apenas passar a instância de classe base no no construtor e acessá-lo através de uma variável de membro.

private class ExtendedClass //: BaseClass - like to inherit but can't
{
    public readonly BaseClass bc = null;
    public ExtendedClass(BaseClass b)
    {
        this.bc = b;
    }

    public int ExtendedProperty
    {
        get
        {
        }
    }
}

downcasting faz sentido, se você tem um objeto da classe derivada, mas é referenciado por uma referência do tipo classe base e por algum motivo você quer voltar a ser referenciado por uma referência tipo de classe derivada. Em outras palavras, você pode downcast para reverter o efeito de upcasting anterior. Mas Você não pode ter um objeto de classe base referenciado por uma referência de um tipo de classe derivada.

Eu não estou dizendo que eu recomendo este. Mas você pode transformar classe base em string JSON e, em seguida, convertê-lo para a classe derivada.

SomeDerivedClass layer = JsonConvert.DeserializeObject<SomeDerivedClass>(JsonConvert.SerializeObject(BaseClassObject));

Não, isso não é possível. Em uma linguagem gerenciada, como C #, ele simplesmente não vai funcionar. O tempo de execução não vai permitir isso, mesmo se o compilador deixa-lo passar.

Você mesmo disse que isso parece pateta:

SomeBaseClass class = new SomeBaseClass();
SomeDerivedClass derClass = (SomeDerivedClass)class; 

Então, pergunte a si mesmo, é class na verdade uma instância de SomeDerivedClass? Não, de modo a conversão não faz sentido. Se você precisa converter SomeBaseClass para SomeDerivedClass, então você deve fornecer algum tipo de conversão, ou um construtor ou um método de conversão.

Parece como se a sua hierarquia de classes precisa de algum trabalho, no entanto. Em geral, não deve ser possível converter uma instância de classe base em uma instância de classe derivada. Não deve ser geralmente de dados e / ou funcionalidades que não se aplicam à classe base. Se a funcionalidade de classe derivada se aplica a todas instâncias da classe base, então ele deve quer ser enrolado na classe base ou puxado em uma nova classe que não faz parte da hierarquia de classes base.

C # linguagem não permite que tais operadores, mas você ainda pode escrevê-los e eles trabalham:

[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Implicit(Base a) { ... }

[System.Runtime.CompilerServices.SpecialName]
public static Derived op_Explicit(Base a) { ... }

Sim. - este é um cheiro de código, e praticamente unhas para baixo o fato de que sua cadeia de herança é quebrada

Meu palpite (a partir da amostra limitada) é que você preferir ter DerivedClass operar em uma instância do SomeBaseClass - de modo que "DerivedClass tem um SomeBaseClass", em vez do que "DerivedClass é um SomeBaseClass". Isto é conhecido como "composição favor sobre a herança".

Como outros já mencionado, o elenco você sugere não é realmente possível. Será que talvez seja um caso em que a Decorator padrão (Head First extrato) lata ser introduzido?

Você já pensou em uma interface que o que está atualmente a sua classe base e a classe derivada tanto iria implementar? Eu não sei os detalhes de por que você está implementando desta forma, mas ele poderia funcionar.

Isso é chamado downcasting e sugestão de Seldaek usar a versão "segura" é o som.

Aqui está um descrição bastante decente com amostras de código .

Isto não é possível, porque como você está indo para obter o "extra" que a classe derivada tem. Como é que o know compilador que você quer dizer derivedClass1 e não derivedClass2 quando você instancia-lo?

Eu acho que o que você está procurando realmente é o padrão de fábrica ou similar para que você possa instanciar objetos sem realmente saber o tipo explícito que está sendo instanciar. No seu exemplo, com o método de "Insert" seria uma interface que instância da fábrica Retorna implementos.

Eu não sei porque ninguém disse isso e eu posso ter falta alguma coisa, mas você pode usar o como palavra-chave e se você precisa fazer um se o uso declaração se.

SomeDerivedClass derClass = class as SomeDerivedClass; //derClass is null if it isnt SomeDerivedClass
if(class is SomeDerivedClass)
    ;

eu fiz esta pergunta há muito tempo

Eu estive recentemente na necessidade de estender um DTO simples com um tipo derivado, a fim de colocar mais algumas propriedades nele. Eu, então, queria reutilizar alguma lógica de conversão que eu tinha, a partir de tipos de bancos de dados internos para os DTOs.

A forma como eu resolvi que era através da aplicação de um construtor vazio nas classes DTO, usá-lo como este:

class InternalDbType {
    public string Name { get; set; }
    public DateTime Date { get; set; }
    // Many more properties here...
}

class SimpleDTO {
    public string Name { get; set; }
    // Many more properties here...
}

class ComplexDTO : SimpleDTO {
    public string Date { get; set; }
}

static class InternalDbTypeExtensions {
    public static TDto ToDto<TDto>(this InternalDbType obj) where TDto : SimpleDTO, new() {
        var dto = new TDto {
            Name = obj.Name
        }
    }
}

então eu posso reutilizar a lógica de conversão do DTO simples ao converter para o complexo. Claro, eu vou ter que preencher as propriedades do tipo de complexo de alguma outra forma, mas com muitas, muitas propriedades do simples DTO, isso realmente simplifica as coisas IMO.

Isso não pode trabalhar. Vai olhar para a página de ajuda ligados pelo erro de compilação.

A melhor solução é usar métodos de fábrica aqui.

Como muitas respostas têm apontado, você não pode abatido que faz sentido total.

No entanto, no seu caso, SomeDerivedClass não tem propriedades que será 'perdido'. Então, você poderia criar um método de extensão como este:

public static T ToDerived<T>(this SomeBaseClass baseClass) 
    where T:SomeBaseClass, new()
{
    return new T()
    {
        BooleanEvaluator = baseClass.BooleanEvaluator,
        GetBaseClassName = baseClass.GetBaseClassName
    };
}

Então você não está lançando, apenas a conversão:

SomeBaseClass b = new SomeBaseClass();
SomeDerivedClass c = b.ToDerived<SomeDerivedClass>();

Este realmente só funciona se todos os dados na classe base é na forma de propriedades legível e gravável.

alças C ++-lo usando um construtor. C ++ Typecasting . Parece um descuido para mim. Muitos de vocês já levantou a questão do que o processo de fazer com as propriedades extras. Eu responderia, o que o compilador fazer quando se cria a classe derivada quando o programador não definir as propriedades? Tenho tratado esta situação semelhante a C ++. Eu criar um construtor que leva a classe base, em seguida, manualmente definir as propriedades no construtor. Isto é sem dúvida preferível para definir uma variável na classe de derivados e quebrando a herança. Também gostaria de escolhê-lo ao longo de um método de fábrica, porque eu acho que o código resultante seria mais limpa procura.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top