解决 将基本对象传递给继承的对象

邦德拉

众所周知的成员
加入
10月24日,2020年
消息
77
编程经验
Beginner
我正在尝试将一个对象传递给一个继承的类/对象的方法。
由于我想尽可能地防止重复的代码。最后一个例子是工作一个,也许是最好的解决方案,即使它有重复的文本块?

你对这一般的看法是什么?你怎么做到了?

示例1 - 没有工作,但优先一个
使用这将只留下我的一块文本即i. "......不玩......"
然而,玩具永远不会被铸造给球(我希望和预期)。因此,让我从球中访问属性颜色。

C#:
        public void InitPlay(Toy toy)
        {
            if (toy is Ball ball)
            {
                toy  = (Ball)toy; // At this point I was expecting toy to be casted to the Ball object...
            }
            else if (toy is Bone bone)
            {
                toy  = (Bone)toy; // At this point I was expecting toy to be casted to the Bone object...
            }

            Console.WriteLine($"\n - Press enter to start playing with the {toy}");
            Console.ReadLine();

            Console.WriteLine(" --------------------------------------------------------");
            // ... and thus be able to reach Color in the Ball object using toy.Color. With no luck.
            Console.WriteLine($" The {TypeOfAnimal}{Name} is now playing with the {toy.Color} {toy} ");
            Console.WriteLine(" - Press enter to finish playing ");
            Console.WriteLine(" --------------------------------------------------------");
        }

示例2 - 工作,但使用重复的文本块

C#:
        public void InitPlay(Toy toy)
        {
            Console.WriteLine($"\n - Press enter to start playing with the {toy}");
            Console.ReadLine();

            if (toy is Ball ball)
            {
// This forces me to have more or less duplicated blocks of text just to reach properties from each inherited object.
                Console.WriteLine(" --------------------------------------------------------");
                Console.WriteLine($" The {TypeOfAnimal}{Name} is now playing with the {ball.Color} {toy} ");
                Console.WriteLine(" - Press enter to finish playing ");
                Console.WriteLine(" --------------------------------------------------------");
            }
            if (toy is Bone bone)
            {
                Console.WriteLine(" --------------------------------------------------------");
                Console.WriteLine($" The {TypeOfAnimal}{Name} is now playing with the {bone.Size} {toy} ");
                Console.WriteLine(" - Press enter to finish playing ");
                Console.WriteLine(" --------------------------------------------------------");
            }
        }
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,721
地点
悉尼,澳大利亚
编程经验
10+
Think about what that first example is doing. The toy parameter is declared as type Toy. What exactly do you think this does:
C#:
toy  = (Ball)toy;
It doesn't matter what you do on the righthand side because you assign the result to the toy variable. If toy is declared as type Toy, how could you possibly get anything other than a Toy reference from it? The actual object was already type Ball so you're not changing the type of the object and you're not changing the type of the variable, so you're doing nothing at all. The cast IS made, but you basically cast it back to the base type again immediately.
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,721
地点
悉尼,澳大利亚
编程经验
10+
我正在尝试将一个对象传递给一个继承的类/对象的方法。
重要的问题是为什么。你告诉我们你想做什么,你向我们展示你是如何尝试的,但你不是在解释你认为自己解决的问题。它几乎肯定误导了。整点是您不会投用基本参考。您将成员声明为基类为 abstract 或者 virtual 默认实现和 然后您将它们覆盖在派生类型中。 这样,您只需通过基准引用访问成员,它将自动调用派生实现。这是多态性 @skydiver. 正在谈论,这几乎是整个遗产的观点。如果您需要调用不常用的成员,那么您几乎肯定不应该首先通过基本类型的引用。
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,893
地点
切萨皮克,va.
编程经验
10+
是时候利用多态性的时间。
 

跳伞运动员

工作人员
加入
2019年4月6日
消息
2,893
地点
切萨皮克,va.
编程经验
10+
跟进 @jmcilkinney. post #3 above, C# is not like Groovy where the types of variables are automatically dynamically typed. (You can use the dynamic keyword to get dynamic types in C#, but personally I find that this actually makes code harder to understand.)
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,721
地点
悉尼,澳大利亚
编程经验
10+
You can use the dynamic keyword to get dynamic types in C#, but personally I find that this actually makes code harder to understand.
It's pretty rare that dynamic should be used. It's the sort of thing that some people might use to hide problems rather than solve them. It can be used to provide late-binding for things like Office Automation, like 选择严格关闭 in VB, and it serves a purpose for things like the ViewBag property in MVC controllers and views. Personally though, I've never had cause to declare something dynamic myself.
 

邦德拉

众所周知的成员
加入
10月24日,2020年
消息
77
编程经验
Beginner
重要的问题是为什么。你告诉我们你想做什么,你向我们展示你是如何尝试的,但你不是在解释你认为自己解决的问题。它几乎肯定误导了。整点是您不会投用基本参考。您将成员声明为基类为 abstract 或者 virtual 默认实现和 然后您将它们覆盖在派生类型中。 这样,您只需通过基准引用访问成员,它将自动调用派生实现。这是多态性 @skydiver. 正在谈论,这几乎是整个遗产的观点。如果您需要调用不常用的成员,那么您几乎肯定不应该首先通过基本类型的引用。
我实际上是这样做但是用摘要。真的不知道为什么我也没有测试虚拟。这是我们在学校教授的那样。
虚拟虚拟工作很好!一秒的修复是所需要的!  (y)
 

jmplhinney.

C#论坛主持人
工作人员
加入
2011年4月23日
消息
3,721
地点
悉尼,澳大利亚
编程经验
10+
There's no need to cast if the member is declared abstract or virtual. In case you're not clear on the distinction, you would use abstract if you wanted to declare the member in the base class but only provide an implementation in each base class, while you would use virtual if you wanted to provide a default implementation in the base class that may or may not be overridden in each derived class. Note that, if you declare a member abstract, you must declare the type abstract as well, which means that you can never create an instance of that class directly. If it exists solely to be a base for other classes anyway, that's not an issue. Here's an example of an abstract method:
C#:
class Program
{
    static void Main()
    {
        var fruits = new Fruit[] {new Apple(), new Orange()};

        foreach (var fruit in fruits)
        {
            DisplayName(fruit);
        }

        Console.ReadLine();
    }

    private static void DisplayName(Fruit fruit)
    {
        Console.WriteLine(fruit.GetName());
    }
}

public abstract class Fruit
{
    public abstract string GetName();
}

public class Apple : Fruit
{
    public override string GetName()
    {
        return "Apple";
    }
}

public class Orange : Fruit
{
    public override string GetName()
    {
        return "Orange";
    }
}
In this case, both 苹果 and 橙子 are required to provide their own implementation of GetName. The output of that code is this:
Apple
橙子
这是一个虚拟方法的示例:
C#:
class Program
{
    static void Main()
    {
        var fruits = new Fruit[] {new Apple(), new Orange()};

        foreach (var fruit in fruits)
        {
            DisplayName(fruit);
        }

        Console.ReadLine();
    }

    private static void DisplayName(Fruit fruit)
    {
        Console.WriteLine(fruit.GetName());
    }
}

public class Fruit
{
    public virtual string GetName()
    {
        return "Unnamed Fruit";
    }
}

public class Apple : Fruit
{
    public override string GetName()
    {
        return "Apple";
    }
}

public class Orange : Fruit
{
}
In this case, 苹果 and 橙子 can provide their own implementation but they don't have to. If they do, calling that method will invoke that implementation, otherwise the default implementation in the base class will be invoked. The output of that code is this:
Apple
未命名的果实
 
最佳 底部