簡體   English   中英

從基類返回派生類實例

[英]Returning derived class instance from a base class

標題可能不清楚,但請看下面的模式

public abstract class Animal
{

    public abstract Dog GetDog { get; }

    public abstract Cat GetCat { get; }

}

public class Dog : Animal
{

    public override Dog GetDog {
        get { return this; }
    }

    public override Cat GetCat {
        get { return null; }
    }

}

這被認為是在基類中具有屬性,返回派生類型的不良做法。 或者我應該做些什么

public abstract AnimalTypeEnum AnimalType { get; }

編輯:根據評論,我想我應該更清楚我想要實現的目標。 DogCat類的新實例將由基於特定條件的單獨函數創建,然后將Animal類型返回給調用者。 調用方法將檢查返回實例的類型並相應地使用它。

public Animal CreateAnimal(string path)
{

    //Process the document in path and create either a new instance of dog or cat

    Dog dg = new Dog();

    return dg;

}

如果你只想要你從中獲得的動物可以這樣做:

public abstract class Animal<T> where T: Animal<T>
{
    public T GetAnimal 
    {
        get { return (T)this; }
    }
}

public class Dog : Animal<Dog>
{
}

public class Cat : Animal<Cat>
{
}

public class Giraffe : Animal<Giraffe>
{
}

你這樣稱呼:

var cat = new Cat();
var dog = new Dog();
var giraffe = new Giraffe();
Cat cat2 = cat.GetAnimal;
Dog dog2 = dog.GetAnimal;
Giraffe giraffe2 = giraffe.GetAnimal;

調用方法將檢查返回實例的類型並相應地使用它。

這是你的問題。 這需要代碼氣味。 你應該能夠把它只是一個對象,而不是以不同的方式對待狗和貓。

如果你需要顯示任何一個動物的內容,那么在兩個類上重寫ToString方法,只需在動物上調用ToString 如果您需要知道狗或貓的名字,那么將一個Name屬性添加到Animal 如果你可能的話,你應該在這里使用多態,這樣無論使用什么對象,它都只是一個Animal並且只是涉及由於同一方法的不同實現而發生的不同事情。

如果你真的,確實需要知道AnimalDog還是Cat那么你可以使用isas運算符; 您不需要添加您在OP中顯示的所有代碼。

不,你做錯了。

更好的方法是使用單一方法。

public abstract Animal getAnimal();

任何派生類都將知道如何返回自己。 我希望這是有道理的。 但是我不認為你會想要歸還動物。 沒有意義。

Animal dog = new Dog() ;
dog.getAnimal(); 

混淆吧?

你可以有一個動物/列表數組,遍歷集合並檢查如下:

if(animal is Dog)

但你還在檢查類型。 如果你想使用一個基類讓它有意義並暴露一個常見的方法。

這是一個真正的基礎設計,因為它違反了開放封閉原則 您希望您的類可以打開以進行擴展,但不能修改。 如果明天你想要添加另一個課程,會發生什么?

public class Donkey : Animal
{
}

您將不得不去更改基類,因此它將具有GetDonkey屬性。 您還必須更改所有使用您的類的類並添加if (animal.GetDonkey == null)

你應該做的是使用這樣的工廠設計模式:

public static class AnimalFactory
{
  public static Dog GetDog()
  {
    return new Dog();
  }

  public static Cat GetCat()
  {
    return new Cat();
  }
}

或者你應該使用@Lews Therin建議的虛擬方法。

擁有只返回被調用對象的屬性似乎沒有用。

也許你只是在尋找一種從超類轉向子類的方法? 如果是這樣,只需使用強制轉換:

Animal a = new Cat();

try
{
    Dog d = (Dog)a;
}
catch (InvalidCastException)
{
    try
    {
        Cat c = (Cat)a;
    }
    catch (InvalidCastException)
    {
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM