简体   繁体   中英

interfaces methods vs classes methods

in Java-8, we can have a method, say, for masking a string , in multiple ways :

Interface Implementation

public interface StringUtil {
    static String maskString(String strText, int start, int end, char maskChar)
            throws Exception{

        if( Strings.isNullOrEmpty(strText))
            return "";

        if(start < 0)
            start = 0;

        if( end > strText.length() )
            end = strText.length();

        if(start > end)
            throw new Exception("End index cannot be greater than start index");

        int maskLength = end - start;

        if(maskLength == 0)
            return strText;

        StringBuilder sbMaskString = new StringBuilder(maskLength);

        for(int i = 0; i < maskLength; i++){
            sbMaskString.append(maskChar);
        }

        return strText.substring(0, start)
                + sbMaskString.toString()
                + strText.substring(start + maskLength);
    }
}

this can be accessed via:

StringUtil.maskString("52418100", 2, 4, 'x')

Now same can be implemented via classes as below

public class StringUtil {

    public String maskString(String strText, int start, int end, char maskChar)
                throws Exception{

            if( Strings.isNullOrEmpty(strText))
                return "";

            if(start < 0)
                start = 0;

            if( end > strText.length() )
                end = strText.length();

            if(start > end)
                throw new Exception("End index cannot be greater than start index");

            int maskLength = end - start;

            if(maskLength == 0)
                return strText;

            StringBuilder sbMaskString = new StringBuilder(maskLength);

            for(int i = 0; i < maskLength; i++){
                sbMaskString.append(maskChar);
            }

            return strText.substring(0, start)
                    + sbMaskString.toString()
                    + strText.substring(start + maskLength);
    }
}

this can be accessed as :

StringUtil su = new StringUtil()
String mask = su.maskString("52418100", 2, 4, 'x')

Question:

Which has to be preferred in which case? So far I understand that interface function are non-testable via mock , so I have to have a wrapper function on top of my interface function - in nutshell - its not unit test friendly and also, being static , you can not override interface methods.

So what other use cases do you consider, if, having an option to write a function?

For any utility developed explicitly I recommend using a class. Default methods in java have a special purpose. These are intended to be utility methods for which implementation needs to be given from vendor ( Remember? - An interface is a contract between Vendor and User ).

For example , if you are using any third party library and a day comes that vendor introduces a new utility feature, then either all the customers have to override that method inside the interface or it's just vendor adds a static default method. This way the code with the new library is still backwards compatible ( at binary code level ).

Precisely, the usage & purpose of a functional interface is well explained in Oracle documentation as below:-

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

For more, you could read the official documentation here .

Also, given this purpose, there is never a requirement to test default methods at your end until you are the one writing such method. A utility method should be tested if it's complex. These utilities for sure could be integration tested. Also, as you said you could write a simple implementation of the interface and test the things. This is similar to testing a abstract class . Read here for more details.

First, in order to define a method in an interface, you need to use the default keyword. Normally, methods are not defined in interfaces - this is probably the biggest difference between classes and interfaces.

Now, you use an interface when you want to GUARANTEE shared functionality across unrelated classes. For example, the Serializable interface guarantees that ANY class implementing this interface is Serializable . I'm not going to explain what "Serializable" means here, but the idea is that instead of having hundreds of classes extend an abstract Serializable class in a messy tree of subclasses, you can simply implement Serializable and use the Power of Polymorphism to refer to your class as a Serializable . Look here for more awesome info: https://www.tutorialspoint.com/java/java_interfaces.htm

In your case, you want a StringUtil class, not a StringUtil interface. Because StringUtil only contains a utility method, you also want to make this method (maskString()) static .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM