Overrloading methods in Java interface [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Is it right to overload method in Java interface like below. And then use the method required in your subclass? If not, is there a better way to do it, kindly suggest.
interface IEmployees{
public List<String> getEmployees(List<String> employees, List<String> departments);
public List<String> getEmployees(List<String> employees, String name);
}
class EmployeesByDept implements IEmployees{
public List<String> getEmployees(List<String> employees, List<String> departments){
// select employees belonging to depts in list and return.
}
public List<String> getEmployees(List<String> employees, String name){
throw new UnsupportedOperationException();
}
}
class EmployeesByName implements IEmployees{
public List<String> getEmployees(List<String> employees, List<String> departments){
throw new UnsupportedOperationException();
}
public List<String> getEmployees(List<String> employees, String name){
// select employees with name in list and return.
}
}

in my opinion overloading an interface this way is not a good idea, as this produces unnecessary/useless code at the implementing class.
I would therefore recommend to write 2 or 3 different interfaces like so
interface IEmployees {
}
interface IEmployeesByDept extends IEmployees {
public List<String> getEmployees(List<String> employees, List<String> departments);
}
interface IEmployeesByName extends IEmployees {
public List<String> getEmployees(List<String> employees, String name);
}
This Way you can cleanly implement the interface that matches your case.

Well, yes and no, it depends.
In general there are most certainly cases for it, where appropriate.
In your case though, probably not, and a lot of your issue comes down to more fundamental design problems. So just by reading your snippet it appears the possibilities are that an IEmployees is:
A set of all employees in a system (for example, all of the employees that work on a project or for a company), or
An arbitrary list of employees (includes 1 but also e.g. search results, etc., the semantic equivalent of a List<Employee>, or
A construct that has a list of employees associated with it (for example, a project, or an organization).
But you say:
it is actually an employee filter class. It will be inherited by other filter classes and will implement any one of the overloaded methods in the interface.
So your first minor problem is the interface name itself. IEmployees leaves a lot up in the air, but if you name it something more self-documenting and descriptive, e.g. IEmployeeFilter, then things start to come together a little more obviously.
So now you have a "filter", and it appears you are trying to have multiple separate filter strategies:
By department
By employee name
Possibly others
These are separate filters, and you state your interface defines a filter, and therefore these are more appropriately organized as two separate subclasses.
So first of all the interface should be what is common to all filters. How the filtering is done is not the common aspect. The filtering itself is. So consider:
interface IEmployeeFilter {
public List<String> getEmployees (List<String> employees);
}
Now you have a filter that makes sense, a single common method, and everything else falls into place, e.g.:
class EmployeeNameFilter implements IEmployeeFilter {
private String name;
public EmployeeNameFilter (String name) {
this.name = name;
}
#Override
public List<String> getEmployees (List<String> employees) {
return employees filtered appropriately
}
}
And:
class EmployeeDepartmentFilter implements IEmployeeFilter {
private List<String> departments;
public EmployeeDepartmentFilter (List<String> departments) {
departments = new ArrayList<String>(departments);
}
#Override
public List<String> getEmployees (List<String> employees) {
return employees filtered appropriately
}
}
Etc. Then when you're ready to use one the interface is always the same:
List<String> employees = ...;
IEmployeeFilter filter = new EmployeeNameFilter("bob"); // or...
// IEmployeeFilter filter = new EmployeeDepartmentFilter(...);
List<String> results = filter.getEmployees(employees); // <- interface always the same
Point is, interfaces exist as a tool to make a job easier. When you run into a situation where you have a bunch of classes implementing that interface but they all implement different parts of it, you're starting to defeat the purpose of an interface, and it's a good hint that there's a fundamental change that needs to be made in your design.
That is, a more general rule of thumb can be: If your interface is making your job harder, or making your code more complicated, you've done something wrong. Otherwise, you've done something right.
Hope that made sense.

Your use-case does not warrant the use of an Interface at all
An Interface represents a contract. You defined the contract as being able to fulfill two requirements. If you know you won't be able to provide both parts of the contract, do not use an interface at all.
Additionally, I strongly doubt you have alternative ways of getting these Employees Lists, another reason not to use interfaces.
Alternative solution
I am guessing your IEmployeesXXX classes have no state variable. This is a good indicator that the methods are utility methods which fetch and return a list of objects.
You should make it a classic Utility class, i.e. an abstract final class with static methods.
Here's an example using your own code, wich becomes much cleaner:
public abstract final class Employeesutility{
public static List<String> getEmployees(List<String> employees, List<String> departments){
// select employees belonging to depts in list and return.
}
public static List<String> getEmployees(List<String> employees, String name){
// select employees with name in list and return.
}
}
Notes going forward
I do not like Utility classes much, I would rather make an intermediate class with rich internal representation, and rich collections wich expose your proposed interface methods. But for your use case, this would probably mean duplicate the entire DB (guessing you have one), which would be stupid. Please consider it if ever you decide to create a true Employee class... which you will when your program becomes big enough.

Related

Multiple instance of class versus array Java

My question which of the following examples represents the right practice ?
What are the advantages and downsides of these approaches.
Is there another(right) way to achieve this?
Let's say I have class
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String print() {
return this.name;
}
}
And use of class like:
public static void main(String[] args) {
List<Person> people = new ArrayList<Person>();
people.add(new Person("Jane Doe"));
System.out.println(people.get(0).print());
}
And then another way to do this:
public class Persons {
private ArrayList<String> persons;
public Persons() {
persons = new ArrayList<String>();
}
public void putPerson(String name) {
persons.add(name);
}
public String print(int id) {
return this.persons.get(id);
}
}
And use of that:
public static void main(String[] args) {
Persons persons = new Persons();
persons.putPerson("John Doe");
System.out.println(persons.print(0));
}
EDIT:
Assume I have 10 000 of these persons.
Is there any downside to creating 10,000 instances of the class?
I would prefer the first way because there is a rare need to create a wrapper class for keeping a collection (like Persons -> Person). It makes sense if the class Persons gets renamed to a Company/Community, which contains a List of workers/persons and provides specific operations over this list.
public String showAllMembers() { ... }
public void notifyAllMembers() { ... }
Also, the second way breaks the Single responsibility principle. It shouldn't take care about printing a person, the class is responsible for adding/removing them. The Persons can provide to you a specific Person, then you have to call a method print() on a given instance:
Persons persons = ...;
persons.getMember(10).print();
Lets say i have 10 000 of these persons. Is there any downside to create 10 000 instance of class?
In any case, you will have to create 10000+ instances. Consider,
10000 Persons + a List
10000 Persons + a Persons + a List
The first one is more object-oriented than the second, which becomes apparent as soon as you start adding more properties to a person.
For example, consider adding a date of birth to a person. When you have class Person, you modify the class, and everyone who has access to it will be able to get it. You will also be passing the date of birth with the Person object, so any method that takes Person as a parameter will have access to that person's date of birth:
static void displayPerson(Person p) {
// Here, we can print both the name and the date of birth / age
}
public static void main(String[] args) {
...
displayPerson(people.get(0));
}
The second approach would require adding a parallel collection to the Persons class. All users of Persons would get access to date of birth, but unless a method takes the full collection as a parameter, it would have access to only the properties that the caller takes from the collection:
void displayPerson(String name) {
// Here, we have no access to person's date of birth
}
public static void main(String[] args) {
...
displayPerson(persons.print(0));
}
In Java, the first approach is the one to go with. It is more in accordance with the OOP way of doing things.
While there is nothing structurally wrong with the second, it doesn't follow the OOP architecture. You may do this kind of operation in C.
In the first approach, you create a Person class which defines what a person is - its properties, methods, etc. This is the object in Object oriented programming. When you need a Person, you then instantiate one and add it to a list of people.
In the second, you create a array, essentially. You can then create an instance of it and fill in the properties you want. However, I see the following drawbacks for this approach:
The object you're adding to the class doesn't exist anymore. Nowhere have you defined what a person is and what properties it has. These properties only exist in the values you add to the array. This can get very confusing and risky after a while.
No getters and setters. Every operation to retrieve a specific property and update it will result in very complex and redundant iterations on your array. In addition, your class can potentially have a very large number of properties, and every time you want to update a property, you'll have to be very careful to get the right index of that property in the array. It's a recipe for disaster.
Also, a putPerson method which just adds a value to the array? Cringy.
Short answer: don't do the second way, in Java, ever.
In my opinion example A is much easier to understand than B hence I would say code readability and maintainability wise it is better.
Reason is that for example B the persons structure actually involves composition of another structure ArrayList to accomplish generics which in example A, you have achieve it by declaring List<Person>.
Example B is also less flexible than A, because it is always a collection whereas example A you can simply use it as a Person and just plug it into different data structures available in Java. Example if you want to keep track of unique person, you can easily come out with a map that is keyed by <name, Person>, whereas example B would not be as clean because you will be doing something like <name, Persons> where each persons would only contain 1 person. Hence extensiblity wise may not be as great as the other one.
Also to me, A is more of the traditional way of doing object oriented because you are representing a real world object as a class whereas B is really just a wrapper of an object.
Obviously there can be a lot of arguments to this, but I'm happy with others input and critic about this answer.

How can I refactor a JAVA method that returns a nested MAP?

public Map<product, SortedMap<Date, ServiceInterval>> getServiceInterval(
Contract pContract, BillCycle pBillCycle)
{
Map<product, SortedMap<Date, ServiceInterval>> returnMap = new HashMap<>();
List<product> productList = getAllproducts(pContract);
for (product product : productList)
{
Date billingDate = getBillingDate(product);
createReturnMap(
product, returnMap,
billingDate, pBillCycle);
}
return returnMap;
}
I was asked to refactor this method (simplified here) because:
Such complex type should not be used in interfaces.
Besides it makes the code difficult to debug.
The implementation should be hidden in the class.
I am not sure it makes sense to refactor this.
Do you agree that is worth refactoring this method?
If yes, what approach would you use? How can one make this easier for debugging?
Thanks
You could replace the nested Map with your own class, e.g. Services that offers the methods the callers need. This class will most likely use or extend a Map. The signature then becomes
public Map<Product, Services> getServiceInterval(Contract pContract, BillCycle pBillCycle)
It makes the code a little easier to read but you are spending development time and effort on it, while most likely not adding much functionality to it. Might make sense if the Services class could be extended with additional logic. Really hard to say without knowing more details.
public Map<Product, SortedMap<Date, ServiceInterval>> getServiceInterval(
Contract pContract, BillCycle pBillCycle)
Such complex type should not be used in interfaces. Besides it makes
the code difficult to debug. The implementation should be hidden in
the class.
I agree. If the service is provided to another client class, it may be cumbersome to use the returned object which is a map of map. So, you could use wrapper for your maps by providing a basic way for client classes to retrieve a ServiceInterval instance matching to input parameters : so containing a getServiceInterval() method in the returned object : public ServiceInterval getServiceInterval (Product product, Date date)
I propose product and date as input parameter as it's how you set your map of map :
Map<Product, SortedMap<Date, ServiceInterval>>
It's pseudo code written on the fly, just to show the idea:
public ServiceIntervalByProduct getServiceInterval(
Contract pContract, BillCycle pBillCycle) {
ServiceIntervalByProduct returnMap = new ServiceIntervalByProduct();
List<product> productList = getAllproducts(pContract);
for (product product : productList)
{
Date billingDate = getBillingDate(product);
createReturnMap(
product, returnMap,
billingDate, pBillCycle);
}
return returnMap;
}
// First level Wrapper class
public class ServiceIntervalsByProduct{
private Map<Product, ServiceIntervalsByDate>> mapByProduct;
public void add(Product product, Date date, ServiceInterval serviceInterval) {
// add in inner map
}
public ServiceInterval getServiceInterval (Product product, Date date){
// get from inner map
return mapByProduct.get(product).getServiceInterval (date);
}
}
// Second level Wrapper class
public class ServiceIntervalsByDate{
private SortedMap<Date, ServiceInterval>> mapByDate;
public void add(Date date, ServiceInterval serviceInterval){
// add in inner map
}
public ServiceInterval getServiceInterval (Date date){
// get from inner map
return mapByDate.get(date);
}
}
I provide add() methods in the wrappers but you can gather all needed data in a constructor if you want to protect data modifications from client classes.
Looking on provided example I don't see any reasone to have nested map at all. As I see from code you have only one billing date per product, so your nested map will have only one element for each product. To make things simpler just create one more class wich wll hold billing date and ServiceInterval, let's call it BillingServiceInterval and return Map<Product, BillingServiceInterval> from your method. Hope this helps
In case for each product you get one Date and one ServiceInterval you could create a simple bean. The method would return a collection of your choice of such beans.

Nested generic collections

Without getting bogged down with specifics, my code represents a library whereby each book is made up of a Set of pages containing a Set of Words.
I have created my own Set implementations:
class PageSet<E> extends HashSet<E>(){
public boolean set(int index, E e){....}
....
}
and
class WordSet<E> extends HashSet<E>(){
public boolean set(int index, E e){....}
....
}
I've got stuck when I try to create a Book in my main class:
Set<Set<Word>> dictionary = new PageSet<WordSet<Word>>();
Which results in a type conversion mismatch. However it will quite happily accept
Set<Set<Word>> dictionary = new PageSet<Set<Word>>();
Could someone please shed some light as to what I'm doing wrong when using a generic setup like this?
Basically, a PageSet<WordSet<Word>> is not a Set<Set<Word>>, because X<Subclass> is not a X<Superclass>.
If you had said
Set<WordSet<Word>> dictionary = new PageSet<WordSet<Word>>();
then that would have worked also.
It's either
Set<Set<Word>> dictionary = new PageSet<Set<Word>>();
or
Set<WordSet<Word>> dictionary = new PageSet<WordSet<Word>>();
Since although WordSet is a subclass of Set, a Set<WordSet> is not a subclass of Set<Set>.
In other words, generics are not covariant, which is different from things like arrays.
In any case, you should not extend collections unless you are trying to create new collection types. Since you cannot restrict the visibilities of superclass methods in a subclass, people will be able to write
WordSet<Word> words = ...;
words.clear();
You probably do not want to give clients that power. Instead, use aggregation instead of inheritance.
class Word {
private String text;
private PartOfSpeech part;
// Constructors, getters, setters, equals, hashCode are elided.
}
class Page {
private int pageNumber;
private Set<Word> contents = new HashSet<>();
public class Book {
private String title;
private List<Page> pages = new ArrayList<>();
}
Pages in a book are ordered linearly, which is why I used lists. I'm not sure why you used sets. But in any case, by encapsulating the collections inside the classes, you can provide client code exactly the interface you want them to use. The visibilities were chosen deliberately; this looks like a cluster of related classes, but you might want to change them.

Compare LinkedList by multiple strings in Java

I have a custom object like this :
Linkedlist<ClassInfo> classes = new LinkedList<ClassInfo>();
Within that, there are accessors for a teacher's name, the class name, the room number, etc. These are all Strings. I have run into a situation where the data in that LinkedList needs to displayed by different parameters (i.e. teacher name, class name, the room number, etc.).
Can anyone supply a quick implementation of how to do this? If I use the Compartor interface, how would I be able tell it which String field to sort the list by? My research also lead me to the Collator, and I was wondering if this would be of use.
Appreciate any help.
Write a different Comparator implementation for each field:
Comparator<ClassInfo> CLASS_NAME_COMPARATOR = new Comparator<ClassInfo>() {
public int compare(ClassInfo class1, ClassInfo class2) {
return class1.getClassName().compareTo(class2.getClassName());
}
};
... // implementations for other fields
...and then sort by whichever comparator is appropriate:
Collections.sort(classes, CLASS_NAME_COMPARATOR);
You will have to provide a custom comparator for every ordering you need to sort your collection to. Eg:
class TeacherComparator implements Comparator<ClassInfo> {
public int compare(ClassInfo c1, ClassInfo c2) {
String teacher1 = c1.getTeacher();
String teacher2 = c2.getTeacher();
return teacher1.compareTo(teacher2);
}
}
class ClassNameComparator implements Comparator<ClassInfo> {
...
}

OO pattern for dividing a collection into groups

I have a list of MyObjects which I need to divide into three groups:
Known good (keep)
Known bad (reject)
Unrecognized (raise alert)
MyObject contains various properties which must be examined to determine which of the 3 groups to put the object in.
My initial implementation (Java) just takes a List in its constructor and does the triage there. Pseudocode:
class MyObjectFilterer {
public MyObjectFilterer(List<MyObject> list) {
// triage items here
}
public List<MyObject> getGood() {
// return sub-list of good items
}
public List<MyObject> getBad() {
// return sub-list of bad items
}
public List<MyObject> getUnrecognized() {
// return sub-list of unrecognized items
}
}
Any issues with this implementation? Is there a better OO choice?
I would probably prefer a static factory method to do the filtering, that then calls a private constructor that takes the three filtered lists, following the good code practice of never doing any serious work in a constructor. Other than that, this looks fine.
There may be multiple approachs. If the problem is generic / repetitive enough, you could define an interface with a method to classify the objects.
interface Selector {
public boolean isGood(MyObject myObject);
public boolean isBad(MyObject myObject);
public boolean isUnknown(MyObject myObject);
}
That way you could change the logic implementation easily.
An other idea would be using the Chain of responsibility.
Your MyObjectFilterer contains a reference to three Objects GoodFilterer, BadFilterer and UnrecognizedFilterer. Each of them contains the following methods: addMethod(MyObject object), getObjects() and addFilter(). Of course they have to implement an interface Filterer.
With the addFilter method you can build the chain. so that the GoodFilterer contains a reference to the BadFilterer and this one contains a reference to the UnrecognizedFilterer
Now you go through your list of MyObjects and call the add method on the GoodFilterer (first one in this chain). Inside the add method you decide if this is good, than you keep it and finish the work, if not pass it on to the BadFilterer.
You keep your three methods for getting the good/bad and unrecognized, but you will pass this to the getObjects() method of the corresponding Filterer
The Benefit is that the logic if this is a good/bad or Unrecognized one is now seperated.
The Downside you would need 3 new classes and 1 Interface.
But like i said, this is just an other idea what you could do.
You should simplify as it's possible. Just make static method in MyObjectFilter with following signature:
public static List filterMyObjects(List data, Group group).
Group is enumeration with three values and it can be used as attribute of MyObject class
I might try something like:
enum MyObjectStatus {
GOOD, BAD, UNRECOGNIZED;
}
class MyObjectFilterer {
private MyObjectStatus getStatus(MyObject obj) {
// classify logic here, returns appropriate enum value
}
// ListMultimap return type below is from Google Guava
public ListMultimap<MyObjectStatus, MyObject> classify(List<MyObject> objects) {
ListMultimap<MyObjectStatus, MyObject> map = ArrayListMultimap.create();
for(MyObject obj: objects) {
map.put(getStatus(obj), obj);
}
}
}
Call classify() to get a Multimap, and extract each category as needed with something like:
List<MyObject> good = map.get(GOOD);
List<MyObject> bad = map.get(BAD);
List<MyObject> unknown = map.get(UNRECOGNIZED);
A nice thing about this solution is you don't have to create/publish accessor methods for each category (unless you want to), and if new categories are created, you also don't add new accessors -- just the new enum and the additional classifier logic.

Categories