I have 3 classes, two inherit from 1:
public class Employee {
private virtual double getBonus() { ... }
private virtual double getSalary() { ... }
}
public class Nepotism : Employee {
private double getBonus() { ... }
}
public class Volunteer : Employee {
private double getSalary() { ... }
}
So the question is sometimes there will be a Volunteer who gets the Nepotism bonus - is there some way to write the constructors to allow overriding/nesting the base class like this:
Employee Bill = new Volunteer(new Nepotism());
I'm thinking something like:
public class Volunteer : Employee {
private Employee _nest;
public Volunteer(Employee nest)
: base() {
_nest = nest;
// now what?
}
}
Basically I want some objects to have the overrides from both classes.
I would like to avoid writing the override methods to check for nested classes.
getSalary() {
return (nest != null) ? nest.salary : salary; // I want to avoid this if I can
}
How can I do this? Am I on the right track? Am I off the rails?
Instead of subclassing, you might want to consider using the Decorator Pattern.
It provides an alternative to subclassing, and it useful when you may need to add "multiple" pieces of additional functionality to a single instance of a class, which is exactly the scenario.
I think you are trying to use inheritance in an ill-advised way. This approach creates a mess of dependences and oddball business rules, which results in a rigid architecture that is hard to use and maintain.
If calculating an employees salary is dependent upon the Employee as well as "bonus traits", then it would be better to separate all three things from each other:
interface IBonusTrait
{
decimal ApplyBonus(Employee employee, decimal currentTotal);
}
class Employee
{
// ...
public decimal BaseSalary { get; set; }
public IList<IBonusTrait> BonusTraits { get; set; }
}
class SalaryCalculator
{
public decimal CalculateSalary(Employee employee)
{
decimal totalSalary = employee.BaseSalary;
foreach (IBonusTrait bonusTrait in employee.BonusTraits)
{
totalSalary = bonusTrait.ApplyBonus(employee, totalSalary);
}
return totalSalary;
}
}
If an object can be both classes at once, then you may need to rethink how you're doing your inheritance.
It seems to me that if a Volunteer can sometimes get a Nepotism bonus, then really, your Volunteer class should have a getBonus() method, and this method really belongs in the base class. It would return zero for most volunteers, but occasionally it wouldn't - there's nothing wrong with that.
Reed Copsey already said, that Decorator Pattern is something to consider.
There is also this youtube video which is very similar to your case (John Skeet is presenting it).
Related
I am making a game in which I have many kinds of soldiers, each kind with their own attributes (speed, attackPower...). Obviously, all of them can Walk, Attack... so I thought that creating an abstract class Soldier with those methods, and subclasses with each unit attributes would be the appropiate. The problem is that I can't use the attributes of derived classes in the base one.
The easy way would probably be implementing the methods in the derived classes, but that would mean lots of duplicated code, and I want to avoid it. In fact, this would make the base class unneccesary.
I have tried several things. As I understand, the closest solution I tried was using abstract/virtual properties, but again I would be duplicating the "get" code for each unit type. Maybe this can't be avoided, but I'd like to, if possible.
There surely exist a simple solution I haven't thought about. ¿Any ideas?
I think about somethink like this:
public abstract class Soldier {
public int AttackPower {
get { return this.power; }
}
public Attack {
Console.WriteLine("Attacked with "+AttackPower+" attack power");
}
}
public class Lancer:Soldier {
int power=5;
}
public class Archer:Soldier {
int power=10;
}
Of course, this is not a correct solution, because the Soldier class doesn't know about the "power" variable, but if I declare the "power" variable in the Soldier class, I get an error because the field name is duplicated.
Any help will be appreciated.
You need an abstract property:
public int AttackPower {
get { return this.power; }
}
protected abstract int Power { get; }
public class Lancer:Soldier {
protected override int Power { get { return 5; } }
}
You could also do a "GetPower" method if you really don't like properties. As you've discovered, if a base class method needs access to the data, you have to declare that data in the base class.
Its not code duplication, its type safety!
Why not just put a Power property in the base class?
public abstract class Soldier {
public int Power {get; set;}
public int AttackPower {
get { return this.Power; }
}
public Attack {
Console.WriteLine("Attacked with "+AttackPower+" attack power");
}
}
public class Lancer:Soldier {
public Lancer()
{
Power = 5
}
}
public class Archer:Soldier {
public Archer()
{
Power=10;
}
}
Some design comments:
Do you need different classes for Archer and Lancer, or can they just be Soldiers that are configured differently?
It would be better to pull property values like this from a data source rather than hard-coding them in the source code. You can embed an XML file or something so it's not easily editable.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I'm trying to understand when I should use an interface vs an abstract class. I was looking at improving my MVC application design and came across this article: http://www.codeproject.com/Articles/822791/Developing-MVC-applications-using-SOLID-principles
In the section about OCP the author gives an example about calculating the price of books. The original code looks like this:
enum Category
{
student,
corporate
}
class Book
{
public double CalculatePrice(double price,Category category)
{
if (category == Category.corporate)
{
price = price- (price * 10);
}
else if (category == Category.student)
{
price = price - (price * 20);
}
return price;
}
}
And his solution looks like this:
abstract class Book
{
public abstract double CalculatePrice(double price);
}
class StudentBook : Book
{
public override double CalculatePrice(double price)
{
return price - (price * 20);
}
}
class CorporateBook : Book
{
public override double CalculatePrice(double price)
{
return price - (price * 10);
}
}
My questions while looking at this solution are:
Why use an abstract class here instead of an interface?
What difference would it make if you were to change this to an interface? Would it really matter?
Thanks for any help in understanding this
The example is artificial because the Book base class has no behaviour, it could just as well be an interface. However a more realistic example would have many other methods such as
getAuthor()
getISBN()
isFiction()
and presumably those behaviours do not change if the book is Student or Corporate so we have a base class with lots of standard behaviours. So Book would genuinely be a Class in that it has useful behaviours that are shared by its derived classes.
Things get a bit more complicated when you have several groups of behaviours, for example a Library Book is a Book but it is also a LendableThing and in Java you can't inherit from two different base classes.
In practice I find that have more Interfaces than I do Abstract Base classes. I define Interfaces as my outward facing contract. That is I write some code that works on objects that my callers give me. I tell them I need something that fulfils this Interface. I don't make any statement about how that is done, just give me something that can CalculatePrice.
The AbstractClass is more for the benefit of someone implementing some code. We're effectively giving a partially written class and then asking the coder to "fill in the blanks". Situations where we can usefully do that tend to be more rare.
An interface is probably the best option in the example you have given, though that may change if the example is expanded.
Broadly speaking, both interfaces and abstract classes can be used to enforce contracts - ie., that a type implementing the contract should behave a certain way. The main difference is that an interface just says what the implementing type should be able to do, whilst abstract classes have the ability to share functionality in addition to a contract.
Your book example could be extended to have extra functionality that has the same implementation across all types of Book, and in that case, you would want to use an abstract class. For example, if I wanted to share an getISBN() method, but the implementation didn't change across the types implementing the contract, then it might make more sense to use an abstract class.
The limitation being that you can only ever implement a single abstract class on any given type but you may implement as many interfaces as you like.
I've seen a few examples where an abstract class implements an interface, and the concrete class implements the abstract class - This way, you get the best of both worlds; 3rd parties don't have to be coupled to your implementation of getISBN() on the abstract class.
Another tangential point is that some mocking libraries will struggle with mocking non-virtual methods and this includes methods on abstract classes - however, they will work perfectly fine with interfaces.
As a TLDR: interfaces are for types where you are not at all interested in how the implementation is done and you only care that a type has certain features. Use abstract classes when you care about how certain parts of the class are implemented but not others.
In your case it would be more suitable using an interface rather than an abstract class. I say so, because you don't provide any implementation of your method that later may be overidden by the classes that inherit your abstract class. All you want it that either a CorporateBook and StudentBook have a method called CalculatePrice with the same signature. Hence, you could define an interface called
public interface IPriceCalculator
{
public double CalculatePrice(double price);
}
and later just make your classes implement this interface:
class StudentBook : Book, IPriceCalculator
{
public double CalculatePrice(double price)
{
return price - (price * 20);
}
}
and
class CorporateBook : Book, IPriceCalculator
{
public override double CalculatePrice(double price)
{
return price - (price * 10);
}
}
On the other hand I would suggest another approach for calculating the value:
public interface IPriceCalculator
{
public double CalculatePrice(double price);
}
public class PriceCalculator
{
public double Discount { get; private set; }
public PriceCalculator(double discount)
{
Discount = discount;
}
public double CalculatePrice(double price)
{
return price - (price*Discount)
}
}
and later inject an object of type IPriceCalculator to the Book constructor.
public class Book
{
// The initial price.
public double Price { get; private set; }
public IPriceCalculator PriceCalculator { get; private set; }
public Book(double price, IPriceCalculator priceCalculator)
{
Price = price;
PriceCalculator = priceCalculator;
}
public double CalculatePrice()
{
return PriceCalculator.CalculatePrice(Price);
}
}
Last,
class StudentBook : Book
{
public StudentBook(double price, IPriceCalculator priceCalculator) :
base(double price, IPriceCalculator priceCalculator)
{
}
}
class CorporateBook : Book
{
public CorporateBook(double price, IPriceCalculator priceCalculator) :
base(double price, IPriceCalculator priceCalculator)
{
}
}
and you create the PriceCalculator of your choice and pass them to the constructors of StudentBook and CorporateBook.
In C#, the difference between using an abstract class versus an interface is mostly about the limitation on polymorphism in CLS languages. In the example that you have given, because the two implementations of CalculatePrice are very simple, using an abstract class instead of an interface adds the polymorphism constraint to all derivatives of Book and brings almost no gain.
I understand that this is a highly simplified example, but hopefully the book will show how the calculation of the price of the book doesn't belong inside the book at all. The first principle of S.O.L.I.D. is Single Responsibility. It is by far the most important. The book class (and derivatives) calculating its price adds a second responsibility to the book (I'm assuming that containing content is the other, and primary, responsibility of the book). This violates the first principle. [It also violates other OOP "rules" like high class cohesion, but that is another topic].
If you wanted to provide access to the calculation of the price to the book class, you would make use of a separate calculating class in the book:
public interface IBookPriceCalculator
{
double CalculatePrice(double price);
}
public class StudentBookPriceCalculator : IBookPriceCalculator
{
public double CalculatePrice(double price)
{
return price - (price * 0.20);
}
}
public class StudentBook
{
IBookPriceCalculator _priceCalculator;
public StudentBook()
{
_priceCalculator = new StudentBookPriceCalculator();
}
public double BasePrice { get; set; }
public double GetPrice()
{
return _priceCalculator.CalculatePrice(BasePrice);
}
}
The answer depends of some factors like common behaviors and level of extensibility. I'm going to explain it creating here an imaginary concept of social network so for us a social network is something that can post messages with images and save an history of posted messages. Then our social networks will share behavior so I will create a base class (abstract class).
public abstract class SocialNetwork
{
public List<string> History { get; private set; }
protected SocialNetwork()
{
History = new List<string>();
}
public void Post(string comment, byte[] image)
{
DoPost(comment, image);
History.Add(comment);
}
protected virtual void DoPost(string comment, byte[] image)
{
}
}
Now I will create our social networks: facebook and twitter
public class Facebook : SocialNetwork
{
protected override void DoPost(string comment, byte[] image)
{
//Logic to do a facebook post
}
}
public class Twitter : SocialNetwork
{
protected override void DoPost(string comment, byte[] image)
{
//Logic to do a twitter post
}
}
Everything look fine until now. Well, imagine we have to handle a totally different kind of social network, for instance some social network that not store messages history, something like Snapchat:
public class Snapchat : SocialNetwork
{
private string _lastMessage;
protected override void DoPost(string comment, byte[] image)
{
//Logic to do a snapchat post
_lastMessage = comment;
ProcessLastMessage();
History.Clear();
}
private void ProcessLastMessage()
{
//Some logic here.
}
}
As you can note above the Snapchat class inherits from SocialNetwork class so Snapchat class will store a history of posts too. But we don’t want it so we have to put code to clear the history list.
Interfaces comes in action
The problem with the implementation above is Snapchat have a thing he don’t need i.e the History so we need a higher level of abstraction here, SocialNetwork base class is what we know how a normal social network, but we need a super abstraction to define what a SocialNetwork do without define any behavior for it so we need define an interface.
public interface ISocialNetwork
{
void Post(string message, byte[] image);
}
Now we will do SocialNetwork class to implement ISocialNetwork:
public abstract class SocialNetwork : ISocialNetwork
{
...
public void Post(string comment, byte[] image)
{
...
}
...
}
Now here is the new Snapchat class:
public class Snapchat : ISocialNetwork
{
private string _lastMessage;
public void Post(string message, byte[] image)
{
//Logic to do a snapchat post
_lastMessage = message;
ProcessLastMessage();
}
private void ProcessLastMessage()
{
//Some logic here.
}
}
Now the design is powerfull enough. Facebook and Twitter share common behavior from SocialNetwork (abstract class) and it implements ISocialNetwork (interface). Snapchat class not share any behavior with Facebook and Twitter but it is a social network too so it implements directly ISocialNetwork interface.
You can read the full article from here: http://www.theagilethinker.com/2015/08/22/an-interesting-example-of-convivence-between-abstract-classes-and-interfaces/
I have a company entity
public class Company : Entity<Company>
{
public CompanyIdentifier Id { get; private set; }
public string Name { get; private set; }
..............
..........
}
A company can be a agent or supplier or both or none. (There are more types) Its behaviour should be change based on types. Agent can get commission and supplier is able to invoice.
What will be the best way to design the entity or entities or value objects? I have an option to add some boolean types and check those values inside methods,
public class Company : Entity<Company>
{
public CompanyIdentifier Id { get; private set; }
public string Name { get; private set; }
public bool IsAgent { get; private set; }
public bool IsSupplier { get; private set; }
..........
public void Invoice()
{
if(!IsSupplier)
{
throw exception.....;
}
//do something
}
public void GetCommission(int month)
{
if(!IsAgent)
{
throw exception.....;
}
//do something
}
..........
}
To be honest, I do not like this. Is there any design pattern which might help to overcome this scenerio? What will you do and why to design this scenerio?
Implement interfaces explicitly, then override the cast operator to only cast to that interface when valid.
public class Company : ...., IAgentCompany, ISupplierCompany ... {
public double IAgentCompany.GetCommission(int month) {
/*do stuff */
}
public static explicit operator IAgentCompany(Company c) {
if(!c.IsAgent)
throw new InvalidOperationException();
return this;
}
}
Explicit implementations of interfaces must be called through their interface, not the concrete type:
// Will not compile
new Company().GetCommission(5);
// Will compile
((IAgentCompany)new Company()).GetCommission(5)
But, now we've overloaded the explicit cast operator. So what does that mean? We can't call GetCommission without casting to IAgentCompany, and now we have a guard to prevent that cast for a company that isn't marked as an agent.
Good things about this approach:
1) You have interfaces that define the aspects of different types of companies and what they can do. Interface segregation is a good thing, and makes the abilities/responsibilities of each type of company clear.
2) You've eliminated a check for every function you want to call that is not "global" to all companies. You do one check when you cast, and then as long as you have it in a variable typed as the interface, you can happily interact with it without any further checking. This means less places to introduce bugs, and less useless checks.
3) You are leveraging the languages features, and exploiting the type system to help make the code more bullet-proof.
4) You don't have to write tons of subclasses that implement the various combinations of interfaces (possibly 2^n subclasses!) with NotImplementedExceptions or InvalidOperationException everywhere in your code.
5) You don't have to use an enum or a "Type" field, especially when you are asking to mix and match these sets of abilities (you'd don't just need an enum, but a flag enum). Use the type system to represent different types and behaviors, not an enum.
6) It's DRY.
Bad things about this approach:
1) Explicit interface implementations and overriding explicit cast operators aren't exactly bread and butter C# coding knowledge, and may be confusing to those who come after you.
Edit:
Well, I answered too quickly without testing the idea, and this doesn't work for interfaces. However, see my other answer for another idea.
I would look into separating the implementation for all those types in different classes. You could start doing this by using an enum to represent the company type.
public enum CompanyType
{
Agent = 0,
Supplier
}
public abstract class Company : Entity<Company>
{
public CompanyIdentifier Id { get; private set; }
public string Name { get; private set; }
public CompanyType EntityType { get; private set; }
public abstract void Invoice();
public abstract void GetCommission(int month);
...
This way you get less public properties.
Next, I'd implement specialized classes for supplier and agent (and then for both and none). You can make Company abstract and any specialized methods abstract as well.
This will allow you to separate the distinct behaviors of each type of entity. Comes in handy when you get back to it for maintenance. It also makes the code easier read/understand.
public class SupplierCompany : Company
{
public SupplierCompany()
{
EntityType = CompanyType.Supplier;
}
public override void Invoice()
{...}
public override void GetComission(int month)
{...}
}
public class AgentCompany : Company
{
public AgentCompany()
{
EntityType = EntityType.Agent;
}
public override void Invoice()
{...}
public override void GetComission(int month)
{...}
}
With this you can eliminate testing for various types in methods like Invoice and GetComission.
As with most DDD questions, it usually boils down to Bounded Contexts. I'd guess you're dealing with some distinct bounded contexts here (this is most obvious from your statement "A company can be a agent or supplier or both or none."). In at least one context you need to consider all Company entities equally, regardless of whether they are Agents or Suppliers. However I think you need to think about whether or not your Invoice or GetCommission operations are applicable in this broader context? I'd say those will apply in more specialized contexts, where the distinction between an Agent and a Supplier is much more crucial.
You may be running into trouble because you're trying to create an all encompassing Company entity which is applicable in all contexts... this is almost impossible to achieve without weird code constructs & fighting against the type system (as is being suggested in your other answers).
Please read http://martinfowler.com/bliki/BoundedContext.html
As a rough idea of how your contexts might look:
Broad "Company" Context
{
Entity Company
{
ID : CompanyIdentifier
Name : String
}
}
Specialized "Procurement" Context
{
Entity Supplier
{
ID : CompanyIdentifier
Name : String
Invoice()
}
}
Specialized "Sales" Context
{
Entity Agent
{
ID : CompanyIdentifier
Name : String
GetComission()
}
}
Does it make sense to try and use the same object in both Procurement and Sales contexts? These contexts have very different requirements after all. One of the lessons of DDD is that we split the domain into these bounded contexts, and do no try to make "God" objects which can do everything.
Every time I want to make something like a "static override" (which is not possible in C#) I find questions that say this is caused by a poor design. How would you design your code to avoid this?
Example: some game with lots of units, each has a different cost (an int or something like that), but each of the subclassses has the same cost. It would make sense here(IMHO) using an "abstract static", but that is not possible. Which is the best way to model this cases?
I usually end up creating an abstract method that returns a static variable that I have to create (and remember!) in each subclass, but then I always depend on having an instance of each class, any other ideas?
No need to use statics here at all. Simply define a base class for all concrete units, that takes the cost as initialization argument:
public abstract class UnitBase
{
public int Cost { get; private set; }
public UnitBase(int cost)
{
this.Cost = cost;
}
}
Taking this as the base for your inheritance tree, you would then go along these lines:
public abstract class Unit1Base : UnitBase
{
public Unit1() : base(<actual_cost>) { }
}
public class ConcreteUnit1 : Unit1Base {}
public class ConcreteUnit2 : Unit1Base {}
This way, each concrete unit will have the desired cost value...
but each of the subclassses has the same cost.
That seems like a good candidate for a base class containing a Cost property that the others will inherit:
public virtual decimal Cost
{
get { return 20m; }
}
Then if anywhere down the chain you have some other price, you could override the Cost property.
You are correct in that you cannot have a static virtual/override property. This can be annoying for the case you describe, which I too have struggled with in the past.
However, you can use static properties... and the new keyword to hide the base implementation.
For example, let's define some units here:
public abstract class BaseUnit
{
public static int UnitCost { get { return 10; } }
}
public class CheapUnit : BaseUnit
{
new public static int UnitCost { get { return 5; } }
}
public class ExpensiveUnit : BaseUnit
{
new public static int UnitCost { get { return 20; } }
}
public class MultipleUnit : BaseUnit
{
new public static int UnitCost { get { return BaseUnit.UnitCost * 4; } }
}
Then a little test program to output their values:
public void Run()
{
Console.WriteLine("Base unit cost:\t\t{0}", BaseUnit.UnitCost);
Console.WriteLine("Cheap unit cost:\t{0}", CheapUnit.UnitCost);
Console.WriteLine("Expensive unit cost:\t{0}", ExpensiveUnit.UnitCost);
Console.WriteLine("Multiple unit cost:\t{0}", MultipleUnit.UnitCost);
}
And we get...
Base unit cost: 10
Cheap unit cost: 5
Expensive unit cost: 20
Multiple unit cost: 40
Ah ha! Exactly what we want. I'm not 100% happy with this solution but I don't know a better way without having to create an instance which I think it silly to access a polymorphic class constant. So I just do it this way.
EDIT: In cases where I found myself doing this, I often opted to move this kind of 'lookup' logic into a manager (singleton) class. For example, UnitManager or similar, where I could pass in a type name ("CheapUnit") and it would look up the cost in a Dictionary.
Just a quick mockup idea:
sealed class UnitManager
{
static readonly UnitManager instance = new UnitManager();
public static UnitManager Instance { get { return instance; } }
Dictionary<string, int> unitCostDictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase); // Ignore Case of Keys
public int LookupUnitCost(string unitType)
{
int unitCost = 0;
unitCostDictionary.TryGetValue(unitType, out unitCost);
return unitCost;
}
}
This also allows dynamic unit cost and centralized notifications when a unit cost may change.
Create a Factory class (static) that returns the instance you want but have the declaration of the factory method return the abstract type?
While I sometimes miss the ability to override a static method in .net, it wouldn't be for this scenario.
Aside from simply using inheritance which you seem to be dead against for some reason I can't fathom, another way to do it might be, to delegate cost to one static class which took unit type as an argument.
Another would be to make cost an attribute of the class and look it up via reflection.
I want my site to support different subscription types, free, premium and etc.
So far I made an abstract class that is like this
public abstract class Limits
{
public int PostLimit { get; protected set; }
protected Limits(int postLimit)
{
PostLimit = postLimit;
}
public bool IsLimitReached(int postCount)
{
return postCount > PostLimit
}
}
public class FreeLimit : Limits
{
private const int postLimit = 1;
public FreeLimit()
: base(postLimit)
{
}
}
So now I did this for all my account types. Now the problem is I don't know how to actually use this class.
For instance I have a service layer call PostService and in this class I have
public void CreatePost(Post post)
{
// do stuff here
}
Now in this method I don't know how to check if they reached the limit. I don't know how to check because I am unsure how to find out if I should be using the FreeLimit or PremiumLimit or what account they have.
I am thinking that I first have to figure out their Role and then somehow use that information to create the right class.
I guess I could have something like
public void CreatePost(Post post, PlanType planType)
{
Limits limit;
switch(planType)
{
case planType.Free:
limit = new FreeLmit()
break;
}
if(limit.IsLimitReached())
{
// do stuff
}
}
I don't like this way as now for every method that needs to check a limit will have to do this. I will have a few methods that require this check in my service layer.
So I was thinking of putting it in my constructor but I don't know if it is good to have a switch statement in a constructor.
You could use an interface ILimit
interface ILimit
{
int PostLimit { get; protected set; }
bool IsLimitReached(int postCount);
}
Now you can have several other classes (Free, Premium, Super) that implement this interface. In your service method CreatePost you can just pass any instance of a class that implements the interface and use it - there's no need to distinguish them anymore since they all support the same interface.
public void CreatePost(Post post, ILimit limit)
{
if(limit.IsLimitReached())
{
// do stuff
}
}
Well, the Limit property is tied to what entity? I suppose it's tied to the Blog (or maybe a Forum) and it is persisted on a DB or something else.
If so, you can do something like this:
public void CreatePost(Post post)
{
if(post.Blog.IsLimitReached())
{
// do stuff
}
}
The Blog.IsPostLimitReached() should call this.Limit.IsLimitReached from itself.
I hope you can understand what I said :)
If you have different types of user, you can tie their accounts (once they've logged in) to different RoleTypes. Then you can use HttpContext.Current.User.IsInRole("RoleName") to see if they are in a specific role, and use that as your basis for showing/hiding functionality.