关于C:如何在从抽象类派生的类中创建新方法?

How to create new methods in classes derived from an abstract class?

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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()在以下代码段中不起作用,编译器将输出一个错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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);
        }
    }
}


您可以向基类中添加方法,而不会出现任何问题。出现编译器错误的原因是您错误地使用了override关键字。

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

因为书、电影和电影都可以"表演",所以您可以考虑将课程设置为这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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 }
}


除了@will的回答(这是正确的),您可以更好地构建您的继承权。例如,您对每种媒体类型执行不同的操作,但每种类型仍会被消耗。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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();
    }
}


不能重写不存在的方法。移除override,然后在使用方法之前进行强制转换,如will提到的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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提到的那样。


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

1
(Book)book.Read_Book();


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

1
    public abstract void Read_Book();