loyalflow
loyalflow

Reputation: 14919

2 classes implement same interface, duplicated code

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

Answers (6)

Nicholas Carey
Nicholas Carey

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

Magus
Magus

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

Habib
Habib

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

edepperson
edepperson

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

JaredPar
JaredPar

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

i3arnon
i3arnon

Reputation: 116636

Yes. You can.

public abstract class BaseUser : IUser
{

}

public class User : BaseUser 
{

}

public class AdminUser : BaseUser
{

}

Upvotes: 13

Related Questions