Expert wanna be
Expert wanna be

Reputation: 10624

Interface Class

I don't understand about using interface class clearly. I read a lot of article and tutorial about interface class related OOP so I know what is the interface but I do understand about using in real project.

For example,

I made IPayment interface class. and I defined 2 method that use common of all payment class.

public interface IPayment 
{
  void MakePayment(OrderInfo orderInfo);
  void MakeRefund (OrderInfo orderInfo);
}

I made 3 payment classes that are CreditCardPayment, PaypalPayment and GooglePayment.

and I defined 2 methods in each classes.

I am confused in this part, I need to make OrderInfo class that contain order information that need to be used for processing payment or refund. And each class need different information.

CreditCartPayment class need Credit Card No, Expiration Date .... But the other payment class are not.

And GooglePayment class need Google Order number but the other class are not.

So, finally the OrderInfo class has to have many extra field. And it look so dirty...

Ex)

Public class OrderInfo 
{
  /* For Common */
  string orderNo {get; set;}
  string customerNo { get; set;}
  decimal amount {get; set;}

  /* For Credit Card */
  string CCNum {get; set;}
  string expDate { get; set;}

  /* For Google */
  string googleOrderID {get; set;}
  ...

  /* For Paypal */
  ...
}

My question is,

In this case, is it right to use IPayment? or I need to define each class with right parameters without Interface class?

I guess the advantage of using Interface class is easy to figure out payment class in later. because the Interface class will show what methods are defined in each payment class. is there the other pros?

and do you have any advice for the understanding Interface class in real world?

[EDIT]

Thank you for all the advice.

I write the example codes again. could you please review this code?

public interface IPayment 
{
  void MakePayment(OrderInfo orderInfo); // !!
  void MakeRefund (OrderInfo orderInfo); // !!
}

public class OrderInfo 
{
  protected string OrderNo {get; set;}
  protected string CustomerNo { get; set;}
  protected decimal Amount {get; set;}
}

public class CreditCardPaymentInfo : OrderInfo
{
  string CCNum {get; set;}
  string ExpDate { get; set;}
}

public class GooglePaymentInfo : OrderInfo
{
  string GoogleOrderID {get; set;}
}

public class PaypalPaymentInfo : OrderInfo
{
  string PaypalID {get; set;}
}



public void MakePayment()
{
    IPayment paymentModule;
    // Get Order Info 
    if(orderType == "Paypal"){
        paymentModule = new PaypalPayment();

        PaypalPaymentInfo orderInfo = new PaypalPaymentInfo();
        orderInfo.PaypalID = "TEST";
    }else if(orderType == "Google"){
        paymentModule = new GooglePayment();

        GooglePaymentInfo orderInfo = new GooglePaymentInfo();
        orderInfo.GoogleOrderID = "TEST";
    }else{
        paymentModule = new CreditCardPayment();

        CreditCardPaymentInfo orderInfo = new CreditCardPaymentInfo();
        orderInfo.CCNum = "1111111111111111";
        orderInfo.ExpDate = "11/11";
    }

    orderInfo.OrderNo = "123";
    orderInfo.CustomerNo = "ABC";
    orderInfo.Amount = 12.20m;

    paymentModule.MakePayment();
}

It occur an error :

Error 1 'com.WebUI.Models.CreditCardPaymentInfo' does not implement interface member 'com.WebUI.Models.IPaymentProcess.makeRefund(WebUI.Models.RefundModel)'

I think I need to fix the Interface class. Anybody know how should I fix it please?

Upvotes: 6

Views: 3228

Answers (6)

supercat
supercat

Reputation: 81115

The purpose of an interface is to allow an entity which holds a reference to an object that implements it to use that object without having to know which of potentially many possible implementations it might happen to be. As such, an interface should generally only define methods which will be potentially useful for all of the classes that implement it.

Based on your scenario, it sound like what's needed is not an interface for the payment-processing class, but rather an interface IOrderWithPayment, for objects which are expected to encapsulate some form of order information and a payment processor object which can accept it (i.e. that particular kind of order information). That interface would then have MakePayment and MakeRefund methods which feed the order information to the payment processor. An object holding an IOrderWithPayment would not have to worry about which type of order information or payment processor was encapsulated within it, since every class that implements IOrderWithPayment would encapsulate order-info and payment-processor types that were compatible with each other.

Note that it would be possible to define a single generic class which could handle all compatible combinations of order-info and payment-processor objects, provided that those objects included suitable declarations about what they could accept, but that would require using some fairly advanced concepts. For now, it's probably easier to define distinct types that encapsulate the compatible combinations of objects.

Upvotes: 1

PapaAtHome
PapaAtHome

Reputation: 604

A interface is used to be able to use classes that do not inherit from the same base. What you did for the three classes looks sound. But it is also possible to create a 'base class' that you can use for inheriting the functions in your interface.

Your problem with OrderInfo does not stem from the interface but more from the fact that you basicly need a different kind of object. More or less, your interface is not suitable for your CreditCartPayment class.

One way out is to create a class inheriting from the OrderInfo class, say CredidCardOrderInfo and use that with the CreditCardPayment class. You can use any instance of the CreditCardOrderInfo class as if it is a OrderInfo instance. Then you add a line

CreditCardOrderInfo info = orderInfo as CreditCardOrderInfo;
if (info == null) throw new ArgumentException("orderInfo has no credit card order info");

It keeps things together... but still is dirty.

Upvotes: 1

Maxim Shoustin
Maxim Shoustin

Reputation: 77904

I'll give you some example about how interface works. Anyways you have a lot of aspects to use interface

Interface inheritance (aka type inheritance): This is also known as subtyping. Interfaces provide a mechanism for specifying a relationship between otherwise unrelated classes, typically by specifying a set of common methods each implementing class must contain. Interface inheritance promotes the design concept of program to interfaces not to implementations. This also reduces the coupling or implementation dependencies between systems. In Java, you can implement any number of interfaces. This is more flexible than implementation inheritance because it won’t lock you into specific implementations which make subclasses difficult to maintain. So care should be taken not to break the implementing classes by modifying the interfaces.

Example:

Lets say we have class named Person.

The Person contains fields like: age, first name, last name, ID, military ID (for military service for example), work place and so on. Now, you want to provide Person info to several institutions like work, army, facebook. Your work don't want to hear everything about your military Id or nick name in facebook. Therefore we create several interfaces: MilitaryItf,WorkItf,WebPersonItf. InWebPersonItfyou define methodsget/setNick name, First Name, gmail and so on. InMilitaryItfyou provideget/set` for age, health, military ID, start/end date of service .... At last each agency use only interested methods derived from 'Person'.

Upvotes: 1

Yogendra Singh
Yogendra Singh

Reputation: 34367

Let me try to explain it with simple example.

Think of a simple method(just for example) saying int rectanglePerimeter(int x, int y). This method simply take two numbers, multiplies them and returns the result. Now you can implement it in two ways:

first: using multiplication

    return x*y;

second: using addition

    int res = 0;
    for(int i=0; i< length; i++){
      res+= width;
    }
    return res;

Now if you want to keep the consumer code of this method independent of the implementation, you can simply define an Interface having the method signature as int rectanglePerimeter(int x, int y). This may be implemented by different implementation bodies in different way but all will have to adhere to the method definition and your consumer code pattern will not change based on the implementaton.

Now let's take more practical example of Database queries execution using Connection interface. Since there are several Database providers, they all have different implementation(database drivers) to support the connection with database, but they all provide the same method support as defined in the Connection Interface e.g. commit(), createStatement(), rollback() & close().

This makes usage independent of the implementation. As you can imagine now, Interface plays a service contract role between consumers and service providers. Its may be possible that both consumers and service providers are your own classes or it may be coming from two different groups/organizations.

Upvotes: 1

Dan J
Dan J

Reputation: 16708

One approach is to make OrderInfo a base class and make your provider-specific payment types subclasses of it, like so:

public class OrderInfo 
{
  /* For Common - Protected members are accessible to subclasses! */
  protected string OrderNo {get; set;}
  protected string CustomerNo { get; set;}
  protected decimal Amount {get; set;}
}

public class CreditCardPaymentInfo : OrderInfo
{
  /* For Credit Card */
  string CCNum {get; set;}
  string ExpDate { get; set;}
}

public class GooglePaymentInfo : OrderInfo
{
  /* For Google */
  string GoogleOrderID {get; set;}
  ...
}

public class PaypalPaymentInfo : OrderInfo
{
  /* For Paypal */
  ...
}

You can then implement your Payment classes like so, and fulfil the requirements of the IPayment interface:

public class PaypalPayment : IPayment
{
    public void MakePayment(PaypalPaymentInfo orderInfo)
    {
      ...
    }

    public void MakeRefund (PaypalPaymentInfo orderInfo)
    {
      ...
    }
}

Since PaypalPaymentInfo can be used wherever OrderInfo is specified, this is a valid implementation of an IPayment. You can follow the same pattern for your credit-card and Google payment implementations.

Upvotes: 6

Jordan Kaye
Jordan Kaye

Reputation: 2887

The right way to implement this would be to make a class for each type of payment, but use them as a general IPayment. So you'd have:

public class CreditPayment : IPayment

public class GooglePayment : IPayment

public class PaypalPayment : IPayment

Then to use a payment:

public class PaymentUser
{
   private IPayment _payment;

   public PaymentUser(//args)
   {
      //Which payment to be used would be based on args. Using a factory here is common
      _payment = new CreditPayment(//args);
   }
}

Now you have an IPayment that's been created for you, and you don't care what type it is other than knowing it fulfills your contract!

So somewhere down the line you can say

public void MakePayment(OrderInfo order)
{
   _payment.MakePayment(order);
}

And you don't even know which type of IPayment you used. This increases extensibility since you don't care what type is executing the method so long as it adheres to the IPayment interface.

Upvotes: 5

Related Questions