2012-12-09 35 views
1

在以下示例中,我使用的是C#。如何在派生自抽象类的类中创建新方法?

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

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); 
     } 
    } 
} 
+0

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

回答

2

除了@Will的回答(这是正确的)之外,你可以更好地构建你的heirarchy。例如,您对每种媒体类型做了一些不同的处理,但每种类型仍然消耗

所以,改变你的基类有一个抽象的基类方法,称为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(); 
    } 
} 
+0

谢谢,它有助于更​​好地理解。 – TheScholar

1

Base_Collection没有一个名为Read_Book方法。要在派生类上调用该方法,您需要将例如

(Book)book.Read_Book(); 
+1

这并不能解决这个事实,即该方法由于不存在而不能被重写。 – rae1

+0

真的,很好的电话rae1n。 –

1

不能覆盖的方法是不存在的。删除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对象,而不是投它,否则,你就必须做在你的程序铸造了很多。也许甚至会重新思考班级的层次结构,像slu men提到的那样。

+0

嘿,我使用你的例子,但编译器仍然不想接受它。编辑:太糟糕了,我无法显示代码,而我评论。 – TheScholar

+0

使用系统; 命名空间polymorphism_test_01 { \t \t 公共抽象类Base_Collection \t { \t \t \t 公共\t INT ID = 0; \t \t public string title =“”; \t \t \t 公共\t Base_Collection() \t \t { \t \t \t \t } \t \t } \t \t 公共类的书:Base_Collection \t { \t \t公共书() \t \t { \t \t \t \t } \t \t \t \t \t公共无效Read_Book() \t \t { \t \t \t \t } \t \t } \t \t 类节目 \t { \t \t public static void Main(string [] args) \t \t { \t \t \t Base_Collection book = new Book(); \t \t \t \t \t \t book.title =“The Dark Tower”; \t \t \t(书)book.Read_Book(); \t \t \t \t \t} \t}} 的 – TheScholar

+0

错误是: “错误CS0201:只有分配,调用,递增,递减和新对象表达式可以用作声明” 和“ 'polymorphism_test_01.Base_Collection' 呢不包含'Read_Book'的定义,并且没有找到接受类型'polymorphism_test_01.Base_Collection'的第一个参数的扩展方法'Read_Book'可以找到(你是否缺少使用指令或程序集引用?)“ – TheScholar

3

你能够方法添加到一个基类,没有任何问题。您收到编译器错误的原因是因为您错误地使用了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 } 
} 
+0

非常感谢,我会牢记这个编程习惯。 – TheScholar

+0

我真正尝试实现的是为其他派生类提供的新方法,这些派生类只针对它们。假设我想在Book类中添加一个名为'Bookmark()'的方法,其他派生类如Game和Movie应该都有这个方法。 – TheScholar

+1

@TheScholar然后,只需将该方法添加到“Book”类中 - 但正如@Will最初提到的,您将无法直接从正在作为“Base_Collection”传递的“Book”实例调用该方法,那么您将要么将其作为派生类型传递,要么在调用方法之前进行强制转换。 – slugster

0

您应该从公众覆盖无效Read_Book(删除替换关键字)或将此函数添加到Base_Collection中,如下所示

public abstract void Read_Book(); 
相关问题