Overloading Java function with List<> parameter - java

I have 2 classes
public class Customer{
...
public String getCustomerNumber();
...
}
public class Applicant{
....
private Customer c;
public Customer getCustomer(){ return c; }
...
}
When presented with a list of customers or applicants I want a function which iterates the list and does something with the CustomerNumber.
I've tried overloading the function
public void processCustomerNumbers(List<Customer> custList)
...
public void processCustomerNumbers(List<Applicant> appList)
...
but these are seen as duplicate methods... is there a nice way of doing this rather than just having 2 differently named functions?

If you make both classes implement a common interface,
interface CustomerNumber {
String getCustomerNumber();
}
public class Customer implements CustomerNumber {
...
public String getCustomerNumber();
...
}
public class Applicant implements CustomerNumber {
....
private Customer c;
public Customer getCustomer() { return c; }
public String getCustomerNumber() { return getCustomer().getCustomerNumber(); }
...
}
then you might be able to do what you want with just a single method:
public void processCustomerNumbers(List<? extends CustomerNumber> appList) {
for (Customer c: appList) {
processCustomerNumber(c.getCustomerNumber());
}
}

The thing about generics in Java is that generic types are erased at runtime, so both of these methods compile to the same signature. You will need to have separate method names, or check the type of the list elements at runtime.

One way to workaround this issue would be to define custom list types like this:
class CustomerList extends ArrayList<Customer> {
...
}
class ApplicantList extends ArrayList<Applicant> {
...
}
Then the following overloading would be legal:
public void processCustomerNumbers(CustomerList custList)
public void processCustomerNumbers(ApplicantList appList)
However, I don't think that this would be a good idea. For a start, it hardwires particular implementation classes into your application's APIs.
A better approach is to define a common interface for Customer and Applicant that allows you to process them with one processCustomerNumbers method. (As described at length in other answers.)

Generics have what is known as type erasure - List<Customer> and List<Applicant> are the same type, the compiler just places compile-time restrictions on what you can do with them.
You could check the type of the first object in the list and call a (differently-named) internal method based on that.

Use array instead.
public void processCustomerNumbers(Customer[] custList)
...
public void processCustomerNumbers(Applicant[] appList)
...
When you try to call these methods with a list, convert the list to array:
List<Customer> customers;
List<Applicant> applicants;
...
processCustomerNumbers(customers.toArray(new Customer[]{});
processCustomerNumbers(applicants.toArray(new Applicant[]{});

Before coming into the method names , the class hierarchy is little bit confusing...
public class Customer{
...
public String getCustomerNumber();
...
}
public class Applicant{
....
private Customer c;
public Customer getCustomer(){ return c; }
...
}
Why should applicant and Customer be
different objects ? Can you tell the
relation between these objects ?

Related

How to use an interface as parameter of other interface with multiple implementations?

I am trying to fix this.
There is a public interface StudentValidation that has this method:
default public void validateStudent(ObjectA inputA){};
default public void validateStudent(ObjectB inputB, ObjectC inputC){};
and it has implementations in two different classes.
So I have
ValidatorStudentSchoolBased that process the value for validateStudent(ObjectA inputA)...
and
ValidateStudentsHomeBased that process validateStudent(ObjectB inputB, ObjectC inputC)
So right now the common interface makes not so much sense and I was wondering if there is any strategy, interface/implementation that I could use for this case so I could be able to send one just parameter like
default public void validateStudent(MyObject myObject)
So far I created MyObject -> StudentClass as an empty interface What is an Empty interface used for and with two specific implementation that are according the needs
So I did this
public interface StudentClass {}
and then
public class StudentClassSchoolBased implements StudentClass () {
ObjectA inputA;
//getters and setters
}
I will also create the implementation StudentHomeBased
Then edited StudentValidation like
validateStudent(StudentClass myObject)
And change the implementations like:
ValidatorStudentSchoolBased(StudentClassHomeBased myObject)
Says does not match the interface (and I cannot override) due the type of the interface is StudentClass and even if StudentClassHomeBased implements it, does not the trick, any idea of how to do what I am trying to do?
Basically, what I want to do is this
create an interface method that as parameter receives another interface with multiple implementations, is that possible?
I think your case can be resolved by using generics and parametrizing StudentValidation.
Is this what you are trying to achieve?
public interface StudentValidation<T>{
public void validateStudent(T student);
}
public class ValidatorStudentSchoolBased implements
StudentValidation<StudentClassSchoolBased>{
#Override
public void validateStudent(StudentClassSchoolBased student) {
}
}
public class ValidateStudentsHomeBased implements
StudentValidation<StudentClassHomeBased>{
#Override
public void validateStudent(StudentClassHomeBased student) {
}
}

Creating an enclosing class for two different objects in java

I'm having an issue that I can't find the right way to resolve by myself.
Basically I have two objects Object1 & Object2 where both of these have two properties of the same type:
public class Object1 {
...
private String name;
private String description;
...
Object1 () {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
public class Object2 {
...
private String name;
private String description;
...
Object2 () {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
Now obviously I made them properties as strings here in the example but in reality they're other types.
NOTE: Object1 and Object2 are actually generated classes from XML models that I need for SOAP servces. So I can't modify them.
In some point in my code I have to access say the 'name' property of either Object1 or Object2 depending on different factors. This point is an event handler so in a certain moment of time it catches an event called with Object1 and other times with Object2.
My guess was to make a single class that would enclose both these types and expose one single "name" property and one single "description" property.
What would a standard way of doing this be?
There basically are two ways to do this:
Use a common interface that expose the getters and setters. Then let both classes implement that interface and let the handler use it.
If possible (both objects don't already extend other superclasses) you could use an abstract superclass and put the properties as well as the getters and setters there. The handler then uses that superclass.
Note that both approaches can be combined, i.e. use an interface for the handler and use an abstract superclass that implements that interface as an adapter class, i.e. you could extend that adapter when possible or just implement the interface when extending the adapter is not possible.
Example:
interface Common {
String getName();
}
abstract class CommonAdapter implements Common {
String name;
String getName() {
return name;
}
//setter as well
}
//just extend the adapter and enjoy
class Object1 extends CommonAdapter {
//specific code for Object1
}
//extending not possible, so implement the interface directly
class Object2 extends SomeOtherClass implements Common {
String name;
String getName() {
return name;
}
}
class Handler {
void handle( Common c ) {
c.getName();
...
}
}
Update:
If the classes are generated, you could create those objects as wrappers and delegate all calls to the actual class, e.g.
class Object1CommonWrapper implements Common {
Object1 delegate;
String getName() {
return delegate.getName();
}
}
make an abstract class and let both classes extend from it
Use interface or abstract class
public interface CommonObject {
//gettter and setter
}
public Class Object1 implements CommonObject { ... }
public Class Object2 implements CommonObject { ... }
public Class MainClass {
public void someMethod() {
if(someCondition) {
CommonObject obj1 = new Object1();
//use obj1
} else {
CommonObject obj2 = new Object1();
//use obj2
}
}
}
Use factory pattern
it depends a bit on the behaviour of said methods. So if:
Both Object1/ Object2 have the absolut identical code for those methods i would go with inheritance, have a superclass that defines those fields/ methods and the two objects extend it.
Both Object1/ object2 must have the same method signature but have to handle the internal logic in different ways i would go with a interface defining the method signature that both Object1/2 must implement.
You can define an interface that both Object1 and Object2 implement. The interface would include the methods that you need to call, but each class can implement them in its own way.
For example, it might look something like this:
public interface Describable {
String getName();
String getDescription();
}
public class Object1 implements Describable {
... implements the methods in some way
}
public class Object2 implements Describable {
... implements the methods in another way
}
With that, whatever code needs to deal with both of these types of objects can refer to them as Describable and take advantage of polymorphism. For example:
Describable eventObject = ...get the object...
eventObject.getName();
eventObject.getDescription();
Or even something like:
public void handle(Describable describable) {
describable.getDescription();
... more stuff...
}
That code doesn't know (or care) what type of object is actually passed in to the method, only that it can interact with it as a Describable.
This is a common idiom in Java and OO design in general. The core libraries use it all over the place.
By the way, inheritance (ie, using a common base super class) is another option. Just be aware that the technique of implementation inheritance has some trade-offs and is often abused/misused. For example see this discussion.

Is it possible to use getters/setters of extended class in Java

I have the following
public abstract class MyData
{
private String sID;
public void setsID(String sID) {
this.sID= sID;
}
public String getsID() {
return sID;
}
}
This base class is being extended by 2 other classes
public class DataTypeOne extends MyData
{
private String sName;
public void setsName(String sName) {
this.sName= sName;
}
public String getsName() {
return sName;
}
}
public class DataTypeTwo extends MyData
{
private String sSummary;
public void setsSummary(String sSummary) {
this.sSummary= sSummary;
}
public String getsSummary() {
return sSummary;
}
}
I am initializing this class as follows
MyData oDataOne = new DataTypeOne();
MyData oDataTwo = new DataTypeTwo();
Reason for that is that I have a factory method which shall give me the class based on type (One or two)
With oDataOne & oDataTwo, I am able to access getsID() from the base class but not the getters & setters of the respective class.
How can I access those? I
You can't access a method that doesn't exist. All you've promised your Java compiler is that oDataOne and oDataTwo are MyData objects. Since the MyData class doesn't have the implementation-specific methods, you cannot ask Java to call those methods (since it doesn't think they exist).
If you want to access those methods, you need to either cast the object to a class that actually has the right methods, or you can add abstract method stubs to your base class, which will tell Java that those methods actually exist.
Type casting is simpler to write in the short term, but less clear, and you may run into more trouble down the road:
((DataTypeOne) oDataOne).getsName();
((DataTypeTwo) oDataOne).getsSummary(); // Throws ClassCastException!
Adding abstract stubs is more robust, but may not make sense if not all concrete subclasses should implement all abstract methods:
public abstract class MyData {
public abstract void setsName(String name);
public abstract String getsName();
public abstract void setsSummary(String summary);
public abstract String getsSummary();
}
public class DataTypeOne extends MyData {
public String getsName() {
// implement
}
public void setsName(String name) {
// implement
}
// Still have to implement these!!!
public String getsSummary() {
// raise an exception or something if appropriate
}
public void setsSummary(String summary) {
// raise an exception or something if appropriate
}
}
// Same for DataTypeTwo
Since you declared the variable as a MyData, you can only access the methods of MyData. You can get to the subclass methods by casting it to DataTypeOne or DataTypeTwo:
((DataTypeOne)oDataOne).getsName()
But you need to be sure it is of type DataTypeOne or you will get a ClassCastException
MyData oDataOne = new DataTypeOne();
this says, that your oDataOne object is of the type MyData. Even if it is created as a DataTypeOne, java can only be sure that it is defiantly a MyData instance.
If you are sure that the MyData instance is in reality also a DataTypeOne instance, you can cast and then access the DataTypeOne methods + the MyData methods.
To make sure that an object is of a specific type test:
if(oDataOne instanceOf DataTypeOne){
((DataTypeOne) oDataOne).getsName(); // this will return the Name if oDataOne is really of the type DataTypeOne
}
An object of type MyData has no knowledge of whether any other classes extends it or not, so there is no way to access members of those classes.
You will have to cast your object to the specific type to access the specific members.
If you find yourself in this situation, you can be pretty sure that your design is flawed. If you need to perform a specific action for each type of MyData extension, add a method, e.g specialAction() to the interface and hide the specifics in there. That eliminates the entire need to find out which subclass you are dealing with.

Creating an EnumMap with a generic type Enum

If I have a bunch of classes that all contain an Enum and EnumMap and I want to create a superclass for those classes.
public interface ColorEnum {
}
class ColorMarbles extends Toy {
enum MARBLE implements ColorEnum
{ BLUE, GREEN }
EnumMap<MARBLE, String> names = new EnumMap<MARBLE, String>(MARBLE.class);
//stuff
// fields
public void populate(ArrayList<String> designer) {
int i = 0;
for(MARBLE marble : MARBLE.values()) {
marble.name = designer.get(i);
i++;
}
}
}
class ColorBalloons extends Toy {
enum BALLOON implements ColorEnum
{ YELLOW, RED }
EnumMap<BALLOON, String> names = new EnumMap<BALLOON, String>(BALLOON.class);
//stuff
// fields
public void populate(ArrayList<String> designer) {
int i = 0;
for(BALLOON balloon : BALLOON.values()) {
balloon.name = designer.get(i);
i++;
}
}
}
How do I make create a superclass to have a generic EnumMap that contains an enum of type ColorEnum like this?
public abstract class Toy {
EnumMap<ColorEnum, String> names;
}
eidt: I realize that I was too vague with my example. Dogs are probably a bad example. I change it to something hopefully more clear.
What I have is a bunch of classes with methods like populate which populates the EnumMap. The names are in a predefined order. Instead of defining populate in every class, I'm hoping to be able to bring it to the Toy superclass so I don't have to keep copy-pasting in each new class type Toy.
Hopefully this will explain more what I'm looking for.
I have a feeling your design is needlessly overcomplicated.
With enums
If you don't require a class inheritance, you can work with enums directly as with top level classes.
public interface Animal {}
public enum Dog implements Animal {
HUSKY("Husky"), LAB("Labrador");
private final String name;
Dog(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Enums can declare fields, methods and implement interfaces like any other Java classes. Their only limitation is that their direct superclass is always java.lang.Enum and they can't be extended.
However every enum constant can have its own set of unique data passed to its constructor. It is even possible that each of the constants can override a common method of that enum with its unique implementation.
A nice tutorial explaining more about the full power of enums:
http://javarevisited.blogspot.cz/2011/08/enum-in-java-example-tutorial.html
Without enums
In case you need an actual class inheritance for sharing some common methods (for example from the Animal superclass), I still would drop the map approach and rather try something more OOP oriented:
public class Animal {
}
public abstract class Dog extends Animal {
public abstract String getName();
public static class Husky extends Dog {
#Override
public String getName() {
return "husky";
}
}
public static class Lab extends Dog {
#Override
public String getName() {
return "labrador";
}
}
}
One mechanism I have used for something like this is to extend a generic base class that has a generic parameter that allows you to pass the Enum details up to it.
This example defines a base Table class for database tables:
public class Table<Column extends Enum<? extends Column>> {
// Name of the table.
protected final String tableName;
// All of the columns in the table. This is actually an EnumSet so very efficient.
protected final Set<Column> columns;
/**
* The base interface for all Column enums.
*/
public interface Columns {
// What type does it have in the database?
public Type getType();
}
// Small list of database types.
public enum Type {
String, Number, Date;
}
public Table(String tableName,
Set<Column> columns) {
this.tableName = tableName;
this.columns = columns;
}
}
Now you can subclass this:
public class VersionTable extends Table<VersionTable.Column> {
public enum Column implements Table.Columns {
Version(Table.Type.String),
ReleaseDate(Table.Type.Date);
// Sadly all of this must be in ALL of your enums but most of the work can be pushed up to `Table`
final Table.Type type;
Column(Table.Type type) {
this.type = type;
}
#Override
public Type getType() {
return type;
}
}
public VersionTable() {
super("Versions", EnumSet.allOf(Column.class));
}
}
and make use of functionality in the parent class that handles your enum.
Note here I am passing an EnumSet to the Table constructor. I am sure you could change this to accommodate your EnumMap requirement if you decide an EnumSet is insufficient.

How to create generic interface methods?

is it possible to create a generic method in interfaces?
say I want to create an interface
public interface Merge {
public void merge(Object host, Object other);
}
then I want the implementing class to implement this, but define the type of host and other.
e.g.
public class FooBazMerge implements Merge {
public void merge(Foo host, Baz other){
// merge some properties
}
}
the reason why I want to do this is so that I can do something like this
public class SomeObject {
private Merge merge;
private Foo foo;
private Baz baz;
public setMerge(Merge merge){
this.merge = merge
}
public void merge(SomeObject anotherObject){
merge.merge(this.foo, anotherObject.getBaz());
}
}
I basically want to delegate the merging responsibility/logic of someObject to FooBazMerge. that way I can change the implementation of how it's merged without having to muck with the domain models every time an adjustment needs to be made.
public interface Merge<A,B> {
public void merge(A host, B other);
}
is this what you are looking for? This is valid syntax. Your implementing class would look like:
public class FooBazMerge implements Merge<Foo, Baz> {
public void merge(Foo host, Baz other){
// merge some properties
}
}
It seems like you want something like...
public interface Merge<T,S> {
public void merge(T host, S other);
}
Check out this page for nice examples of generic interface implementation.
This should help of how to implement one.
http://www.java2s.com/Code/Java/Language-Basics/Agenericinterfaceexample.htm

Categories

Resources