【问题标题】:How to create new methods in classes derived from an abstract class?如何在派生自抽象类的类中创建新方法?
【发布时间】:2012-11-26 19:52:34
【问题描述】:

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

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

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() { }
    }
}

在下面的sn-p中调用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);
        }
    }
}

【问题讨论】:

  • 您收到编译器错误的原因是因为您正在创建一个Book 对象并将其转换为其基本类型。当您尝试在其上调用 Read_Book() 时,这将不起作用,因为在 Base_Collection 类型上没有定义 Read_Book()Read_Book() 仅在 Book 类型上定义。您将通过将您的书创建为Book book = new Book(); 并从您的Read_Book() 方法定义中删除override 关键字来修复您的编译器错误。

标签: c# oop inheritance polymorphism abstract-class


【解决方案1】:

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

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

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

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 }
}

【讨论】:

  • 我真正想要实现的是为其他仅特定于它们的派生类提供新方法。假设我想在 Book 类中添加一个名为“Bookmark()”的方法,其他派生类如 Game 和 Movie 都应该有这个方法。
  • @TheScholar 然后将该方法添加到 Book 类中 - 但正如 @Will 最初提到的那样,您将无法直接从 Book 的实例调用该方法作为Base_Collection 传递,您要么必须将其作为派生类型传递,要么在调用方法之前对其进行强制转换。
  • 您只能访问在该类型上定义的成员。因此,对于您的基类,除非您强制转换它,否则您将只能访问基类成员。为了在派生类上使用这些方法,您需要将对象转换为与派生对象相同的类型。
【解决方案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();
    }
}

【讨论】:

  • 谢谢,这有助于更好地理解。
【解决方案3】:

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

(Book)book.Read_Book();

【讨论】:

  • 这并不能解决该方法一开始就无法被覆盖的事实,因为它不存在。
【解决方案4】:

不能覆盖不存在的方法。删除 override 然后在访问方法之前强制转换,就像 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 提到的那样。

【讨论】:

  • 嘿,我正在使用您的示例,但编译器仍然不想接受它。编辑:太糟糕了,我评论时无法显示代码。
  • 使用系统;命名空间 polymorphism_test_01 { 公共抽象类 Base_Collection { 公共 int id = 0;公共字符串标题=“”; public Base_Collection() { } } public class Book : Base_Collection { public Book() { } public void Read_Book() { } } class Program { public static void Main(string[] args) { Base_Collection book = new Book(); book.title = "黑暗之塔"; (书)book.Read_Book(); } } }
  • 错误是:“错误CS0201:只有赋值、调用、递增、递减和新对象表达式可以用作语句”和“'polymorphism_test_01.Base_Collection'不包含'的定义Read_Book' 并且没有扩展方法 'Read_Book' 接受类型为 'polymorphism_test_01.Base_Collection' 的第一个参数(您是否缺少 using 指令或程序集引用?)“
  • 好的,在您的示例中,您在 Base_Collection 中添加了 Read_Book 方法,但实际上我不想这样做。假设我真的需要添加一个特定于 Book 派生类但其他类的方法?
  • @TheScholar 实际上没有,我只是删除了 override 关键字。 ReadBook 仅适用于 Book 类。但是,您应该真正实现类似于其他答案提到的东西,至少要避免强制转换。
【解决方案5】:

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

    public abstract void Read_Book();

【讨论】:

    猜你喜欢
    • 2018-09-12
    • 2013-11-30
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    • 1970-01-01
    • 2014-11-16
    相关资源
    最近更新 更多