How to extend class?

2019-09-02 13:40发布

问题:

I'm making a change to an API that serves data. Some of the searches require data about an author and take a IAuthor object. The API has an IAuthor interface and a single concrete class that implements IAuthor called Author.

I need to add a boolean property, IsNovelist that will change the semantics of some but not all searches.

I've heard about the open/closed principle and it would seem that changing the IAuthor and/or Author classes would violate this. How then to make this simple change?


UPDATE:

Perhaps I was concentrating on the wrong class. I don't want to add behaviour to Author class (it's just a way of passing parameters to the API). So a Decorated author wouldn't need a boolean flag because it would be isNovelist == true by implication.

I need to change the behaviour of the GetBooks method given an author who is flagged as being a novelist. So something more like this but my thinking is probably wonky because now I'm changing (not extending) the Books class:

//Before
class Books 
{
   public Books[] GetBooks(IAuthor author){
       // Call data access GetBooks...
    }
}


//After
class Books 
{
   public Books[] GetBooks(IAuthor author){
       // To maintain pre-existing behaviour
       // call data access GetBooks with SQL param @isNovelist = false...
       // (or don't pass anything because the SQL param defaults to false)
    }

   public Books[] GetBooksForNovelist(IAuthor author){
       // To get new behaviour
       // call data access GetBooks with SQL param @isNovelist = true
    }
}

回答1:

Solution 2 :

class Program
{
    private static void Main(string[] args)
    {

        IAuthor author = new Novelist();
        author.Name = "Raj";

        // i guess u have check if author is a novelist
        // the simple way is by safe typecasting

        Novelist novelist = author as Novelist;

        if (novelist != null)
        {
            Console.WriteLine("Wohoo, i am a novelist");
        }
        else
        {
            Console.WriteLine("Damn,i cant write novel");
        }


    }

Solution 1 :

public enum AuthourType
{
    Novelist,
    Other
}

public interface IAuthor
{
    string Name { get; set; }
    AuthourType Type { get; set; }

}

public class  Novelist : IAuthor
{
    public string Name { get; set; }
    public AuthourType Type { get; set; }
    // incase u dont want it to be set to other value
    /*        
    public AuthourType Type
    {
        get { return type; }
        set
        {
            if (value != AuthourType.Novelist)
            {
                throw new NotSupportedException("Type");
            }
            type = value;
        }
    }
    */
}


回答2:

Here is how you do using the decorator pattern

interface IAuthor
{
    void someMethod();
}

class Author:IAuthor{

    public void someMethod(){
        //Implementation here
    }
}

//Class that will add the extra behavior.
class DecoratedAuthor : IAuthor
{
    IAuthor author;
    public bool isNovelist{get;set;}//Add the extra Behavior

    public DecoratedAuthor(IAuthor auth)
    {
        this.author = auth;
    }

    public void someMethod(){
        //Call the Author's version here
        author.someMethod();

        //check if he is a novelist
        isNovelist = true;
    }

}


public class program{
    public static void Main(string[] args)
    {
        IAuthor auth = new Author();
        DecoratedAuthor novAuth = new DecoratedAuthor(auth);

        DecoratedAuthor.someMethod();
        //see if he is a novelist
        Console.WriteLine(novAuth.isNovelist);

    }

}


标签: c# oop interface