简体   繁体   中英

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

In the following example I am using C#.

I have created an abstract class Base_Collection , and then I derive other classes from it ( Book , Movie , Game ). However, I don't know how to add new methods that can be used for those new children classes without getting a compiler error.

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

Calling book.Read_Book() doesn't work in the following snippet, the compiler will output an error:

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

You are able to add methods to a base class without any problem. The reason you're getting a compiler error is because you used the override keyword incorrectly.

In order to use the override keyword the method name and signature must match the method name and signature in the parent class, and method must be marked as virtual or abstract in the base class. The difference between the two is answered here .

Since the book, movie, and film can all be "performed", you may want to consider making your classes like this:

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

Further to the answer from @Will (which is correct), you could structure your heirarchy a little better. For example, you do something different with each of the media types, but each type still gets consumed .

So change your base class to have an abstract base method called Consume() , which is then overridden and actually implemented in each derived class, this way you can pass around instances of your base class and there is no need for casting to invoke the Consume() method on each media type:

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

Base_Collection doesn't have a method named Read_Book . To call the method on the derived class, you need to cast eg

(Book)book.Read_Book();

You cannot override a method that doesn't exist. Remove the override and then cast before accesing the method, like Will mentions.

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();
    ...
}

However, I would just create a Book object, rather than cast it, otherwise you'll have to do a lot of casting in your program. Maybe even rethink the class hierarchy, like slugster mentions.

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

    public abstract void Read_Book();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM