Implementing a common interface from through different classes Java - java

I have the method here to add users to a database, based on given arguments (username, password, etc...)
public boolean addUser(String username, String password,
String f_name, String l_name, String email)
{
try
{
pstmnt = conn.prepareStatement("INSERT INTO users VALUES (user_id_increment.nextval,?,?,?,?)");
//do stuff...
And one here to add User objects to an ArrayList
public boolean addUser(User username)
{
if(users.contains(username))
//do stuff...
However, I'm trying to implement both cases through a common interface:
public interface Admin_DAO {
public void addUser();
//other methods...
I'm not sure how I could do this so that both classes can implement the same interface, given that they require different arguments.
Any ideas?

You can't implement an interface method with multiple different signatures.
Now that I've got that out of the way, let me clarify. An interface includes method signatures. You cannot implement that interface by changing the method signatures, because that fundamentally changes how Java sees the method. Java considers two methods with different signatures to be just as different as if they had different names. So you could write a class with two different addUser methods, but only one of them will override the method from the interface.
If your methods require totally different information, they probably shouldn't be implementing the same interface. However, if they require essentially the same information but in a different format, then you should write an interface that accepts a common format for that information, and then they can both implement it. So for instance, if it turns out that a User looks basically like this:
public User(String username, String password, String f_name, String l_name, String email) {
}
Then you can make your interface accept User objects.
public interface Admin_DAO {
public void addUser(User u);
}
And then you can implement that as needed in your different classes.

Change your Admin DAO to accept a User data object to accommodate any future changes to the number of arguments that you need to pass without affecting the public interface.
public interface AdminDAO {
public boolean addUser(User user);
}
Then implement this method as an overload in your User DAO. I also suggest that you store or pass your passwords around as char[] to prevent interning (addition into the Java string pool).
public class UserDAO implements AdminDAO {
public boolean addUser(User user) {
return addUser (user.getUsername(), user.getPassword(),
user.getFName(), user.getLName(), user.getEmail());
}
public boolean addUser(
String username, char[] password,
String f_name, String l_name, String email) {
// ...
}
}
EDIT : (extending an interface in respone to OP's comments below)
public interface IUser {
public boolean addUser(User user);
}
public interface AdminDAO extends IUser {
// other DAO methods
}
public class UserDAO implements AdminDAO {
// ...
}
public class UserUtil implements IUser {
public boolean addUser(User user) {
return addUser (user.getUsername(), user.getPassword(),
user.getFName(), user.getLName(), user.getEmail());
}
public boolean addUser(
String username, char[] password,
String f_name, String l_name, String email) {
// ...
}
}

Wrap the arguments in an interface.
public interface IUser{
String getName();
String getPassword();
//etc
}
Then have your Admin_DAO accept IUsers.
public interface Admin_DAO{
void addUser(IUser user);
boolean contains(IUser user);
}
This allows abstraction of Admin_DAO implementation details. It could be a database, or just an in memory datastructure. Having it accept data wrapped in an interface lets you pass in the same type of objects.

Ideally, there should be two classes. As the information used for both the method is same. You interface should look like this :
interface Admin_DAO{
public void addUser(User user);
}
And you should have two separate classes implementing this interface:
class AddUserToList implements Admin_DAO{
public void addUser(User user){
//add user to list
}
class addUserToDB implements Admin_DAO{
public void addUser(User user){
//add user to list
}
Each class should actually serve one purpose.

Short answer You cannot.
Here are a couple of my favorite paragraphs from GoF Design Patterns book. The text below should clear any query you have. You may want to read it a couple of times.
Every operation declared by an object specifies the operation's name,
the objects it takes as parameters,and the operation's return
value.This is known as the operation's signature.The set of all
signatures defined by an object's operations is called the interface
to the object. An object's interface characterizes the complete set of
requests that can be sent to the object. Any request that matches a
signature in the object's interface may be sent to the object.
A type is a name used to denote a particular interface. We speak of an
object as having the type "Window" if it accepts all requests for the
operations defined in the interface named "Window." An object may
have many types, and widely different objects can share a type.Part
of an object's interface may be characterized by one type, and other
parts by other types.Two objects of the same type need only share
parts of their interfaces. Interfaces can contain other interfaces as
subsets. We say that a type is a subtype of another if its interface
contains the interface of its supertype. Often we speak of a subtype
inheriting the interface of its supertype.
Interfaces are fundamental in object-oriented systems. Objects are
known only through their interfaces.There is no way to know any thing
about an object or to ask it to do anything without going through its
interface. An object's interface says nothing about its
implementation-different objects are free to implement requests
differently.

Related

Using an extend from a class or use composition

I have a abstract class called user and I'm wondering if i have to add another class that requires a user does it need to extend from the class below or do i need to reuse the user class via composition, all help is greatly appreciated.
public abstract class User implements Serializable {
protected String userName;
protected String emailAddress;
protected Date dob;
protected Password password;
// Initialisation Constructor
public User(String userName, String emailAddress,
int d, int m, int y,
String cPW, String uEPW, int noTries){
this.userName = username;
this.emailAddress = emailAddress;
this.dob = new Date(d, m, y);
}
this.password = new Password(cPW, uEPW, noTries);
// Assume that User also has ==>
// 1. a toString() method,
// 2. an equals() method, and
// 3. appropriate set() and get() methods
}
Its not clear why this class needs to be marked as abstract. An abstract class is one that cannot be instantiated, but you have written a constructor suggesting that it can?
Since an abstract class can't be instantiated on its own the only way it can be used is via inheritance.
In this scenario though, it would seem that your User class should not be abstract, and therefore other classes can simply use it via composition.
In general, prefer composition over inheritance where it makes sense, and if there is a need for inheritance, prefer to inherit purely abstract interfaces rather than classes containing implementation.
Inheritance is an "is-a" relationship.
Composition is a "has-a" relationship.
So if the new class is for example, Admin - An admin is-a user so use inheritance.
If the new class is something like UserAccount - use composition. The account is not a user but is associated with one.

Using an anonymous class to return values in Java

Consider the following code:
public interface MyClass {
public final String getMyObject1();
public final String getMyObject2();
}
public class MyClass1 implements MyClass {
private String myObject1;
private String myObject2;
public MyClass1(String myObject1, String myObject2) {
this.myObject1 = myObject1;
this.myObject2 = myObject2;
}
public String getMyObject1() {
return myObject1;
}
public String getMyObject2() {
return myObject2;
}
}
public interface MyClass2 extends MyClass {
public static MyClass2 newInstance(String myObject1, String myObject2) {
return new MyClass2() {
public String getMyObject1() {
return myObject1;
}
public String getMyObject2() {
return myObject2;
}
};
}
}
And I use them like
public static void func(MyClass m) {
m.getMyObject1();
m.getMyObject2();
}
func(new MyClass1(o1, o2));
func(MyClass2.newInstance(o1, o2));
I wonder how they differ and if I only need to read from the values (i.e. to use MyClass as a "struct" to pass values), using the anonymous class can it be a simpler approach?
Otherwise, what are the draw backs?
One core rule of programming: try to not surprise your readers.
Your approach here to use a static class within an interface as "factory" method is very surprising (and believe me: I have seen a lot of Java code).
If at all, the more "common" way of handling such things: create a static class with a slightly similar name, you know, like there is java.lang.Object and java.lang.Objects that carries some useful static helper methods.
And beyond that, there is already a class in Java that helps with arbitrary numbers of "named" values; and that is called a Map!
Finally: there are some good arguments for "DTO"s (data transfer objects) but esp. for "beginners", you should rather look into "real" OO designs; based on the SOLID principles. In that sense: design real classes that exactly model your problem domain; and that provide helpful abstractions. A struct with an arbitrary number of members ... doesn't fall into either category.
The problem here is not the code necessarily but the design. I would be interested to know the real world use case you are trying to design here.
Surely there are limitations in the second approach like you cannot update the value of your objects at all once your class is created as you just have a way to get the value of the passed objects back.
Coming back to Design:
An interface is supposed to be an action which your class can perform if it implements that interface. In your case you are trying to return the value of two instance variables using the two methods in your interface which is a kind of action but it ignores the basic principle of encapsulation.
If your class defines/owns those instance variables it should have the getters and setters for that. You should not require an interface to do that. So ideally your interface should not be required. Any other class which uses MyClass1 object should directly use the getters and setters of the MyClass1.

Abstract method with variable list of arguments

I haven't quite found an elegant way to solve this issue. I have an abstract class that several other classes are inheriting with an abstract method that can contain anywhere from zero to 4-5 arguments of varying types.
public abstract class Item {
public abstract void use();
}
For instance, I have a Book class that inherits this and takes no arguments when overriding use(), I have a Key class that inherits and takes a String and a Queue as arguments when overriding, etc...
I've tried using generics but I have to input the number used, such as Item, when it actually depends on the class.
public abstract class Item<T,U> {
public abstract void use(T arg1, U arg2); //Number of arguments/types could be more or less
}
I've tried sending a variable list of Objects but the object types are always variable and I've unsure as to the syntax to receive in the inheriting classes.
public abstract class Item<T> {
public abstract void use(T... arguments);
}
public class Book extends Item<?> {
public void use(?);
}
public class Book extends Item<String, Queue> { //Wrong number of arguments since I can't use Item<T...>
public void use(String str, Queue q); //fails
}
I may just be doing something wrong - can anyone offer any assistance or insight?
I've struggled with the same question, and there's not a perfect answer, but I can give you a few things to consider. First, you're basically trying to do something that is inherently against Object Oriented Programming, which is that you're trying to create a variable interface. The point of an interface is that code that gets an abstract version of the object (the Item rather than the Book, for example), knows how to invoke the use() method. This means that they must know what can be passed to the use() method. If the answer depends on the implementation of the abstract class or interface, then you need to ensure that the code using it actually knows what kind of implementation (Book, etc.) that it's using, otherwise it's not going to know how to invoke use() with the appropriate parameters anyway. It sounds like you need to refactor your code, in all honesty.
However, there is a way to answer your question as stated without refactoring the architecture. You could create a class that's data is all of the different types of parameters that could possibly be passed to the use() method, have the calling code set the fields of that class, and then pass that to the use() method. For example:
public class UseParameters {
private String string;
private Queue queue;
// Any other potential parameters to use(...)
public void setString(String string) {
this.string = string;
}
public String getString() {
return string;
}
// All of the other accessor methods, etc.
}
Then, you could define the use method in Item like this:
public abstract void use(UseParameters params);
And any code using an Item would have to set the parameters of the object appropriately:
Item item = // However you're going to get the item
UseParameters params = new UseParameters();
params.setString("good string");
params.setQueue(new Queue());
item.use(params);
I just want to point out that if the code above knows the Item is a Book (which is how it knows to set the String and Queue, then why not just get a Book and skip needing an abstract class with a variable use() method altogether? But I digress. Anyway, the Book would then implement the use() method like so:
#Override
public void use(UseParameters params) {
if(params.getString == null || params.getQueue() == null)
// throw exception
// Do what books do with strings and queues
}
I think that gets you what you want, but you should consider refactoring, I think.
What you want is the Value Object Pattern.
Define a class that encapsulates the various parameter types into one value object, and have the abstract method accept a parameter of this type. Each variation of parameters you were considering would have its own value class.
Then simply add a generic type to the class and have the abstract method accept a parameter of that type:
public abstract class Item<V> {
public abstract void use(V v);
}
To use it, suppose MyItem needs a value object of type MyValueClass:
public class MyItem extends Item<MyValueClass> {
public void use(MyValueClass v) {
}
}
If the types to be used as argument are always variable I don't see a reason to use generics. Just use plain Object type:
public abstract class Item {
public abstract void use(Object ... arguments);
}
public class Book extends Item {
public void use(Object ... arguments) { ... }
}
The best approach I can think of is to group the items according to the behavior of their use() method.
Example
public abstract class QueueableItem {
public abstract void use(String, Queue);
}
public abstract class OrdinaryItem{
public abstract void use(String);
}
If the grouped items share a common behavior (common as in same method signature & return value), you can define and extend a parent class that will contain the definition of this common behavior.
Yes, we can provide parameters to abstract method but it is must to provide same type of parameters to the implemented methods we wrote in the derived classes.

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.

How to pass generic parameters in Java

In Java I have two classes:
Class A
{
public String ID;
public Object Name;
}
Class B
{
public String ID;
public Object Name;
}
I want to have a method where I can pass it either a Class A or B object:
public void SomeMethod(??? arg)
{
String id = arg.ID;
Object name= arg.Name;
}
Is it possible to pass an object of either class A or B to this method? If so, how is the method's signature written?
The only solution I can think of is to create an interface that both Class A and B implements containing get and set methods to set the fields ID and Name. Then the method's signature would be a parameter whose type is the interface. I was hoping that maybe there is a simpler way, possibly with generics?
You are correct with needing to use an interface (or an abstract class) with the appropriate method signatures. To java the two class are different with nothing (beside Object) in common. You need to create a class hierarchy refelecting the commonality between them.
Use method overloading.
public void SomeMethod(A arg)
{
String id = arg.ID;
Object name= arg.Name;
}
public void SomeMethod(B arg)
{
String id = arg.ID;
Object name= arg.Name;
}
You could make an interface and have A and B implement it. It really depends on your application. For small programs, I would just stick with method overloading since it just introduces unnecessary abstraction into your program.
For larger applications where extensibility is a priority, you may want to consider using an interface. Suppose later on you want to write classes C and D which also have SomeMethod(). Using an interface makes it so that you don't have to go through your entire code and overload appropriate methods over and over again.
If you know for sure that A and B are the end of the story, then there's no need to make an interface.
EDIT: If there's a lot of code to be duplicated, then make a helper method:
public void SomeMethod(A arg)
{
HelpMePlease( arg.ID, arg.Name );
}
public void SomeMethod(B arg)
{
HelpMePlease( arg.ID, arg.Name );
}
private void HelpMePlease( String id, Object name ) {
// 1000 lines of code here
}
You don't need generic types. Simple inheritance will do the job
abstract class Base {
public String ID;
public Object Name;
}
class A extends Base {
}
class B extends Base {
}
public void SomeMethod(Base arg)
{
String id = arg.ID;
Object name= arg.Name;
}
Generics are intended to improve type safety during compilation.
What you are asking about seems to be something akin to C++ concepts or various other languages' duck typing.
In Java, if some sequence of operations need to be performed on two disparate types, you need to introduce an interface or resort to scripting/reflection.
Define two interfaces, hasID and hasName, and then:
public class MyClass<A extends hasID & hasName>{
public void SomeMethod(A object) {
String id = object.getID();
Object name= object.getName();
}
}
Where getID and getName are defined on their respctive interfaces.

Categories

Resources