1

在以下示例中,我使用 C#。

我创建了一个抽象类Base_Collection,然后从中派生出其他类(Book、、、MovieGame。但是,我不知道如何添加可用于这些新子类的新方法而不会出现编译器错误。

namespace polymorphism_test_01
{
    abstract class Base_Collection
    {
        public int id = 0;
        public string title = "";

        public Base_Collection() { }
    }
}    

namespace polymorphism_test_01
{
    class Book : Base_Collection
    {
        public Book() { }

        public override void Read_Book() { }
    }
}    

namespace polymorphism_test_01
{
    class Game : Base_Collection
    {
        public Game() { }

        public void Play_Game() { }
    }
}   

namespace polymorphism_test_01
{
    class Movie : Base_Collection
    {
        public Movie() { }

        public void Watch_Movie() { }
    }
}

调用book.Read_Book()在以下代码段中不起作用,编译器将输出错误:

namespace polymorphism_test_01
{
    class Program
    {
        public static void Main(string[] args)
        {
            Base_Collection book = new Book();

            book.title = "The Dark Tower";
            book.Read_Book();

            Console.WriteLine(book.title);
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
}
4

5 回答 5

3

您可以毫无问题地将方法添加到基类。您收到编译器错误的原因是您错误地使用了override关键字。

为了使用override关键字,方法名称和签名必须与父类中的方法名称和签名匹配,并且方法必须标记为virtualabstract在基类中。两者的区别在这里得到解答。

由于书籍、电影和电影都可以“表演”,您可能需要考虑将您的课程设置为:

abstract class Base_Collection
{
    public int id = 0;
    public string title = "";

    public Base_Collection() { }

    public virtual void PerformAction() { } // or public virtual void PerformAction(){ }
}

class Book : Base_Collection
{
    public Book() { }

    public override void PerformAction() { // read book }
}

class Game : Base_Collection
{
    public Game() { }

    public override void PerformAction() { // play game }
}

class Movie : Base_Collection
{
    public Movie() { }

    public void PerformAction() { // watch movie }
}
于 2012-12-09T00:35:28.290 回答
2

除了@Will 的答案(这是正确的),您可以更好地构建您的层次结构。例如,您对每种媒体类型执行不同的操作,但每种类型仍会被消费

因此,将您的基类更改为具有一个名为 的抽象基方法Consume(),然后在每个派生类中重写并实际实现该方法,这样您就可以传递基类的实例,而无需强制转换来调用Consume()每个媒体上的方法类型:

public abstract class Base_Collection
{

    public int id = 0;
    public string title = "";

    public Base_Collection() {   }

    public abstract void Consume();

}

public class Book : Base_Collection
{
    public Book() {   }

    public override void Consume()
    {
        //do book reading stuff in here
    }
}

public class Movie : Base_Collection
{
    public Movie() {   }

    public override void Consume()
    {
        //do movie watching stuff in here
    }
}



public class SomeOtherClass
{
    public void SomeMethod(Base_Collection mediaItem)
    {
        //note that the book/movie/whatever was passed as the base type
        mediaItem.Consume();
    }
}
于 2012-12-09T00:32:15.920 回答
1

Base_Collection没有名为 的方法Read_Book。要在派生类上调用该方法,您需要强制转换,例如

(Book)book.Read_Book();
于 2012-12-09T00:24:18.023 回答
1

不能覆盖不存在的方法。在访问方法之前删除overrideand then cast,就像 Will 提到的那样。

class Book : Base_Collection
{
    public Book()
    {

    }

    public void Read_Book()
    {

    }
}


public static void Main(string[] args)
{
    Base_Collection book = new Book();

    book.title = "The Dark Tower";
    (Book)book.Read_Book();
    ...
}

但是,我只会创建一个 Book 对象,而不是强制转换它,否则您将不得不在程序中进行大量强制转换。甚至可能重新考虑类层次结构,就像 slugster 提到的那样。

于 2012-12-09T00:27:34.377 回答
0

您应该从 public override void Read_Book() 中删除 override 关键字,或者将此函数添加到 Base_Collection,如下所示

    public abstract void Read_Book();
于 2012-12-31T13:43:23.020 回答