Reputation: 14919
I have an interface:
public interface IUser
{
}
And then 2 classes that implement this interface:
public class User : IUser
{
}
public class AdminUser : IUser
{
}
Now the problem I see is that there is duplicate code between User and AdminUser when implementing a method in the interface.
Can I introduce an abstract class that would implement the common code between User and AdminUser somehow?
I don't want AdminUser to inherit from User.
Upvotes: 6
Views: 7601
Reputation: 74365
That's the problem with interfaces rather than abstract classes: no shared implementation. Interfaces were intended as a workaround for the lack of multiple inheritance.
In general, your object model should be a forest of small inheritance trees.
One solution is to create a small mix-in class that provides the required functionality and implements the interface. Include that in your class and expose its methods via pass-through methods that implement the interface by invoking the mix-in.
interface IFoo
{
int MethodA() ;
int MethodB() ;
}
class IFooMixin : IFoo
{
public int MethodA() { ... }
public int MethodB() { ... }
}
class Widget : IFoo
{
private IFooMixin IFooImplementation = new IFooMixin() ;
public int MethodA()
{
int rc ;
// inject your specific behavior here
rc = IFooImplementation.MethodA() ;
// and/or inject it here
return rc ;
}
public int MethodB()
{
int rc ;
// inject your specific behavior here
rc = IFooImplementation.MethodB() ;
// and/or inject it here
return rc ;
}
Upvotes: 1
Reputation: 1312
The core of your problem here is that you seem to be trying to use interfaces to describe what a class is, rather than it's functionality. An interface is best use to specify things such as IAuthorizeable or IEnumerable. They indicate varying behavior on a common theme.
For cases like yours, as others have suggested, you want to use inheritance unless you can change how you structure things. My preference would be to create a user class which contains strategies for the parts that vary, rather than inheriting.
There's a large difference between inheriting shared features and allowing differences to be extendable. If you compose User
with interfaces rather than create base classes, if more roles need to be added in the future, you only have to add another implementation of the changing behavior, rather than making another subclass that may share different things with the other two classes.
An example:
class User
{
private IAuthenticator authenticator;
public string Name { get; set; }
public Guid Id { get; set; }
public User(string name, Guid id, IAuthenticator authenticator)
{
Name = name;
Id = id;
this.authenticator = authenticator;
}
public Rights Authenticate()
{
return authenticator.Authenticate(Name, Id);
}
}
Where the authenticators could be things like:
public class WebAuthenticator : IAuthenticator
{
public Rights Authenticate(string name, Guid id)
{
// Some web specific authentication logic
}
}
And Rights:
[Flags]
public enum Rights
{
None = 0, Read = 1, Write = 1 << 1, Execute = 1 << 2
}
The end result is that your code is reusable, extensible, and flexible. Generally the fact that a user is an administrator should not give the user class extra logic, but rather constrain things that use the specific instance.
Upvotes: 3
Reputation: 223402
Your class User
should be base class for AdminUser
From the name of the classes it appears that your class User
should be base class and AdminUser
should inherit from that class. If that is not the case then you can create a base class for both User
and AdminUser
implement your interface in the base class and inherit that in User
and AdminUser
.
public interface IUser
{
void SomeMethod();
}
public abstract class User : IUser
{
public abstract void SomeMethod();
}
public class AdminUser : User
{
public override void SomeMethod()
{
throw new NotImplementedException();
}
}
public class NormalUser : User
{
public override void SomeMethod()
{
throw new NotImplementedException();
}
}
Upvotes: 3
Reputation: 1035
Yes, you can create concrete methods in the abstract where functionality is same.
Create virtual methods where there is a common need but different implementation
then in your inheriting classes, add methods to each that are unique to their implementation
Upvotes: 2
Reputation: 755467
Sounds like you should introduce a UserBase
class that both User
and AdminUser
could inherit from that has the shared code
class UserBase : IUser {
// Shared Code
}
class User : UserBase { }
class AdminUser : UserBase { }
Upvotes: 5
Reputation: 116636
Yes. You can.
public abstract class BaseUser : IUser
{
}
public class User : BaseUser
{
}
public class AdminUser : BaseUser
{
}
Upvotes: 13