6

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.

2
  • 4
    Answer is: yes, you can Commented Feb 7, 2014 at 17:56
  • 1
    I think the correct answer might be: You're using interfaces wrong, and an abstract class may be less effective than composition. Commented Feb 7, 2014 at 18:12

6 Answers 6

13

Yes. You can.

public abstract class BaseUser : IUser
{

}

public class User : BaseUser 
{

}

public class AdminUser : BaseUser
{

}
Sign up to request clarification or add additional context in comments.

Comments

5

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

2 Comments

Why did you choose to not make UserBase an abstract class?
@TravisJ the OP didn't specify whether the shared code could or couldn't stand alone. Felt weird to have an abstract base if I didn't have an abstract memeber to include with the definition.
3

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

}

Comments

3

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.

Comments

2

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

Comments

1

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

1 Comment

I honestly doubt interfaces were added because of a lack of MI. There are many reasons to use them, such as to enforce contracts - in which case they can be considered 'safer' than inheritance because you know there will be no other logic to worry about in the base class. To class them as a workaround is to ignore their separate purpose.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.