Creating common method for two classes not using inheritance in java - java

I'm just wondering if there is any way to create two classes that aren't related but have the same implementation of method. I know there are interfaces and static methods but it seems like they are good only when you have static field in class. Is this possible to do that kind of thing when method uses field that is specific to exact object?
I know it's a bad practice writing code like this but I'm just curious.
EDIT:
I mean something like this:
public class Person implements MakingOlder {
private int age;
}
public class Cat implements MakingOlder {
private int age;
}
public interface MakingOlder {
public static void makeOlder() {
this.age += 2;
}
}
I don't want to make common base class for Person and Cat and interface is not working. I'm trying to avoid writing the same implementation twice and copying the code.

Sure, it's called "composition + delegation", and it's often a good practice to replace inheritance by this :
https://en.wikipedia.org/wiki/Composition_over_inheritance
public class Person implements AgingObject {
private int age;
private AgingBehavior agingBehavior;
void makeOlder() {
agingBehavior.makeOlder(this);
}
//(...)
}
public class Cat implements AgingObject {
private int age;
private AgingBehavior agingBehavior;
void makeOlder() {
agingBehavior.makeOlder(this);
}
//(...)
}
public class AgingBehavior {
void makeOlder(AgingObject agingObject) {
agingObject.setAge(agingObject.getAge() + 2);
}
}
public interface AgingObject {
int getAge();
void setAge(int age);
}

...or you can use default implementation in Java 8+...
public interface MakingOlder {
public default void makeOlder() {
setAge(getAge() + 2);
}
int getAge();
void setAge(int age);
}
and of course your Person and Cat implements MakingOlder...

Probably your interface is not working because you are trying to implement a method within the interface:
public static void makeOlder() {
this.age += 2;
}
In order to make it work, try to add the default keyword so that it looks like:
default Integer makeOlder(Integer age) {
age += 2;
return age;
}
Then the class, which implements that interface, will just need to contain something like:
public class Dummy implements AA {
Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
To test the result you can call something like:
Dummy d = new Dummy();
d.setAge(d.makeOlder(7));
System.out.println(d.getAge());
d.setAge(d.makeOlder(d.getAge()));
System.out.println(d.getAge());

Related

How do I define a field in a subclass by strictly following a given UML?

I'm trying to implement the UML diagram below using java:
I only got recently exposed to UMLs and according to my understanding, I cannot set a field inside SBank or PBank to define their rate of interest. It can also be seen that in the class Bank there is no implementation for defining the rate of interest like using a setter method. I am looking for advice on how to go about this, or is there something wrong with the given UML? Below are some sample code I used to try and implement the UML into code:
public class BankInfo {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Bank {
private BankInfo info;
private int rateOfInterest;
public Bank(BankInfo info) {
this.info = info;
}
public void displayInterestRate(){
}
public int getRateOfInterest(){
return rateOfInterest;
}
}
public class SBank extends Bank{
private int rateOfInterest = 8;
public SBank(BankInfo info) {
super(info);
}
#Override
public int getRateOfInterest() {
return rateOfInterest;
}
}
This UML:
Does not show any rateOfInterest field in any class. What it shows is Bank is abstract and has an int-returning abstract method: getRateOfInterest(). You can tell the class and method are abstract because their names are italicized.
public abstract class Bank {
// other members...
public abstract int getRateOfInterest();
}
The UML further shows you need to override getRateOfInterest() in both SBank and PBank, both of which extend Bank, and return that implementation's rate of interest. You will be returning the value directly rather than storing it in a field. For example, SBank would look like:
public class SBank extends Bank {
public SBank(BankInfo info) {
super(info);
}
#Override
public int getRateOfInterest() {
return 8;
}
}
I got the value of 8 from the UML diagram which states:
Interest Rate of SBank is 8 %.

How do I minimize the amount of code for a hierarchy

This is for learning. I have an interface that is implemented by 2 classes, and I am supposed to reduce the amount of code I use in order to keep things more clean and less messy. Currently, the code looks like this:
public abstract class VClass implements IntFace {
protected String name;
public VClass(String name) {
this.name = name;
}
public int value (SClass sc) {//comes from a diff class
return sc.lookup(name);
}
public String getName() {
return name;
}
#Override
public String toString() {
return getName();
}
}
public abstract class NClass extends VClass implements IntFace {
public Number(String name) {
super(name);
this.name = name;
}
public int value (SClass sc) {
return sc.lookup(name);
}
public String getName() {
return name;
}
#Override
public String toString() {
return getName();
}
}
public interface IntFace {
public int value (SClass sc);
public String toString (int num);
}
can this code be more condensed?
You can remove the following things from your code:
implements IntFace from NClass declaration. Since NClass extends VClass, it implements IntFace as well.
this.name = name; from NClass constructor. name is initialized in a superclass constructor
value and getName methods from NClass. These methods are implemented in a superclass.
public modifier from interface methods declaration. Methods in interfaces are public by default.
Now you can also make name field private since it's no longer used in a NClass.

how to implement fluent builder with inheritance in java

problem
I want to create a class with a fluent builder, both of which can be inherited and extended. Base class should have all the common and mandatory fields, children should have different optional fields
simple example below (best, simplistic usecase I could come up with ;p)
base: Animal
name
age
static Builder
impl: Snake extends Animal
length
static Builder extends Animal.Builder
impl: Spider extends Animal
numberOfLegs
static Builder extends Animal.Builder
and I'd like to use it in one of those ways (most preferred one is the first one):
Spider elvis = Spider.name("elvis").age(1).numberOfLegs(8).build();
Spider elvis = Spider.builder().name("elvis").age(1).numberOfLegs(8).build();
Spider elvis = new Spider.Builder().name("elvis").age(1).numberOfLegs(8).build();
what I want to achieve is
user of this builder will have to provide some minimal information (so the system can work without problems), otherwise he won't be able to build that object
all the optional fields can be declared, with no particular order, after mandatory fields are there
it is possible that I'll need to add some mandatory fields for children, but that can be handled with ease by just changing the first method called in the builder
I don't want to have any casts outside those classes (here: in Main), but I don't mind them inside this code (here: in Animal or Spider)
so far I failed and I'd be very grateful if you could please help me find a way out of it :)
or maybe there is just a different approach that I should think about?
most valuable sources I used
http://blog.crisp.se/2013/10/09/perlundholm/another-builder-pattern-for-java
http://egalluzzo.blogspot.com/2010/06/using-inheritance-with-fluent.html
Generic fluent Builder in Java
work done so far
the code so far can be found below. there are some traces of the things I tried and failed, there are some unused or just weird stuff (best example is IBuildImpl). Those are left to give you an understanding of what I tried, but if you think that this needs moderation - please let me know and I'll clean them up
Base
package fafafa;
public abstract class Animal<T> {
String name; //mandatory field, one of many
Integer age; //mandatory field, one of many
public String getName() {
return name;
}
#Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
'}';
}
interface IName {
IAge name(String name);
}
interface IAge {
IBuild age(Integer age);
}
interface IBuild<T extends Animal<T>> {
T build();
}
public abstract static class Builder<T extends Animal<T>, B extends Builder<T, B>>
implements IName, IAge, IBuild<T> {
protected T objectBeingBuilt;
protected abstract B that();
protected abstract T createEmptyObject();
Builder(){
this.objectBeingBuilt = createEmptyObject();
System.out.println();
}
#Override
public IAge name(String name) {
objectBeingBuilt.name = name;
return that();
}
#Override
public IBuild age(Integer age) {
objectBeingBuilt.age = age;
return that();
}
// #Override
// public T build() {
// return objectBeingBuilt;
// }
}
}
Impl
package fafafa;
public class Spider extends Animal<Spider> {
Integer numberOfLegs; //optional field, one of many
private Spider() {
}
public Integer getNumberOfLegs() {
return numberOfLegs;
}
#Override
public String toString() {
return "Spider{" +
"numberOfLegs='" + numberOfLegs + '\'' +
"} " + super.toString();
}
// public static Builder<Spider, Builder> name(String name) {
// return (Builder) new Builder().name(name);
// }
interface INumberOfLegs {
IBuild numberOfLegs(Integer numberOfLegs);
}
interface IBuildImpl extends IBuild<Spider>, INumberOfLegs {
#Override
Spider build();
}
public static class Builder extends Animal.Builder<Spider, Builder> implements IBuildImpl {
#Override
protected Builder that() {
return this;
}
#Override
protected Spider createEmptyObject() {
return new Spider();
}
public IBuild numberOfLegs(Integer numberOfLegs) {
objectBeingBuilt.numberOfLegs = numberOfLegs;
return that();
}
public Spider build() {
return objectBeingBuilt;
}
}
}
Main
package fafafa;
public class Main {
public static void main(String[] args) {
Spider build = new Spider.Builder().name("elvis")
.age(1)
.numberOfLegs(8) //cannot resolve method numberOfLegs
.build();
System.out.println(build);
}
}
Looks like to many generics in a code, I've tried to simplify it a little.
Animal
package come.stackoverflow.builder;
public abstract class Animal {
private final String name; //mandatory field, one of many
private final Integer age; //mandatory field, one of many
Animal(final String name, final Integer age) {this.name = name; this.age = age;}
public String getName() {return name;}
public Integer getAge() {return age;}
#Override public String toString() {return String.format("Animal {name='%s', age='%s'}'", name, age);}
interface IBuild<T> {
T build();
}
public abstract static class AnimalBuilder<B extends AnimalBuilder, T extends Animal> implements IBuild<T> {
String name;
Integer age;
public B name(final String name) {this.name = name; return (B) this;}
public B age(final Integer age) {this.age = age; return (B) this;}
}
}
Spider
package come.stackoverflow.builder;
public class Spider extends Animal {
private final Integer numberOfLegs; //optional field, one of many
private Spider(final String name, final Integer age, final Integer numberOfLegs) {super(name, age); this.numberOfLegs = numberOfLegs;}
public Integer getNumberOfLegs() {return numberOfLegs;}
#Override public String toString() {return String.format("Spider {numberOfLegs='%s'}, %s", getNumberOfLegs(), super.toString());}
public static class SpiderBuilder extends AnimalBuilder<SpiderBuilder, Spider> {
Integer numberOfLegs;
public SpiderBuilder numberOfLegs(final Integer numberOfLegs) {this.numberOfLegs = numberOfLegs; return this;}
public Spider build() {return new Spider(name, age, numberOfLegs);}
}
}
Main Test
import come.stackoverflow.builder.Spider;
public class Main {
public static void main(String[] args) {
Spider build = new Spider.SpiderBuilder()
.name("elvis").numberOfLegs(8).age(1)
.build();
System.out.println(build);
}
}
Execution Result:
Spider {numberOfLegs='8'}, Animal {name='elvis', age='1'}'
The problem of your code is the interface:
interface IAge {
IBuild age(Integer age);
}
This will always return the basic IBuild interface with no parameter, no matter, if the implementation implements it with some argument. Actually even returning it with the parameter wouldn't extend the builder with additional methods.
The parameter in the builder needs to be the extended builder, and not the type to be built.
All interfaces for the common parameters need to be parametrized with it to allow propper continuation.
Here is a suggestion:
1. Don't use IName interface. Replace it with static entry method of the builder
2. Parametrize IAge interface
3. No common builder needed. It can be replaced with inline lambda implementation
Here is the code:
#FunctionalInterface
public interface IAge<B> {
B age(Integer age);
}
public class AnimalBuilder implements IBuild<Animal> {
private final String name;
private final Integer age;
private Integer numberOfLegs;
private AnimalBuilder(String name, Integer age) {
this.name = name;
this.age = age;
}
// Builder entry method
public static IAge<AnimalBuilder> name(String name) {
return age -> new AnimalBuilder(name, age);
}
public AnimalBuilder numberOfLegs(int value) {
numberOfLegs = value;
return this;
}
#Override
public Animal build() {
return new Animal(name, age, numberOfLegs);
}
}
This allows following usage:
AnimalBuilder.name("elvis").age(1).numberOfLegs(8).build();
The problem is in the abstract builder :
public abstract static class Builder<T extends Animal<T>, B extends Builder<T, B>>
implements IName, IAge, IBuild<T> {
...
#Override
public IAge name(String name) {
objectBeingBuilt.name = name;
return that();
}
#Override
public IBuild age(Integer age) {
objectBeingBuilt.age = age;
return that();
}
So, all your concrete builders return the same IBuild<T> interface when you invoke the age() method.
and as you see :
interface IBuild<T extends Animal<T>> {
T build();
}
this interface doesn't allow to return a object where you have methods to set properties with your builder.
When you invoke the name() method, you also don't get the builder :
interface IAge {
IBuild age(Integer age);
}
You should declare age() and name() in the abstract builder like that :
public abstract static class Builder<T extends Animal<T>, B extends Builder<T, B>>{
...
public B name(String name) {
objectBeingBuilt.name = name;
return that();
}
public B age(Integer age) {
objectBeingBuilt.age = age;
return that();
}
In this way, at the compile time, the concrete builder will return the builder of the animal you are creating when you will invokebuilder.age(..).
Besides, I don't understand why having a builder interface for name and another one for age. What is interest to handle IAge and IName interfaces ?
It seems a too low level information to be useful in your builder.
Why not simply declaring you base builder like that :
public abstract static class Builder<T extends Animal<T>, B extends Builder<T, B>>
implements IBuild<T> {
protected T objectBeingBuilt;
protected abstract B that();
protected abstract T createEmptyObject();
Builder(){
this.objectBeingBuilt = createEmptyObject();
System.out.println();
}
public B name(String name) {
objectBeingBuilt.name = name;
return that();
}
public B age(Integer age) {
objectBeingBuilt.age = age;
return that();
}
}
I have not tested the code.

Generic method for not related objects - java

I have following two classes:
public Class A{
String name;
Integer age;
//setters and getters
}
And
public Class B{
String name;
Integer age;
Integer height;
//setters and getters
}
and following method
public String getMyName(B b){
return b.getName()+" "+b.getAge()+" "+b.getHeight();
}
Is it possible to refactor this method to use generics which will allow me to call it for objects of those two different classes?
E.g
public <T> String getMyName(T t){
return t.getName()+" "+t.getAge()+( t instanceof B ? " "+t.getHeight() : "");
}
Of course it doesn't work since t doesn't know methods getName, getAge and getHeight.
Classes are not in any relation( I know that they can inherit from one common class and use <T extends C> but they don't have superclass or common interface)
No, without using a common interface or superclass this is not possible with generics. You could use reflection but I'd advice against that and suggest providing a common interface instead.
As others said, there would be other ways to handle that case (e.g. method overloading or passing Object and using instanceof and casts) but if you can use a common interface, I'd still go that way.
Note that Java generics are unlinke C++ generics/templates which would allow what you want to do - and there are good reasons for that difference.
This is the place where people shout the line Programming with interfaces.
Take a an interface and add common methods to it and create a generic method which takes that interface as a argument.
That makes your life easy.
You can use instanceof to check whether is compatible type and if it is, cast object to your type and call methods. It is not elegant way, but still. So this way, you can use your method as generic. :)
You can dynamically adapt them on the fly - something like:
public class A {
String name;
Integer age;
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
}
public class B {
String name;
Integer age;
Integer height;
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
public Integer getHeight() {
return height;
}
}
// Create a common interface.
public interface AorB {
public String getName();
public Integer getAge();
// Use Java 8 to implant a default getHeight if it is missing.
default Integer getHeight() {
return 0;
}
}
// Dynamicaly adapt each type.
public String getMyName(A a) {
// Adapt it on the fly.
return getMyName(new AorB() {
#Override
public String getName() {
return a.getName();
}
#Override
public Integer getAge() {
return a.getAge();
}
});
}
public String getMyName(B b) {
// Adapt it on the fly.
return getMyName(new AorB() {
#Override
public String getName() {
return b.getName();
}
#Override
public Integer getAge() {
return b.getAge();
}
#Override
public Integer getHeight() {
return b.getHeight();
}
});
}
// Your method almost untouched.
public String getMyName(AorB ab) {
return ab.getName() + " " + ab.getAge() + " " + ab.getHeight();
}
public void test() {
A a = new A();
a.name = "A";
a.age = 10;
B b = new B();
b.name = "B";
b.age = 10;
b.height = 12;
System.out.println("A:" + getMyName(a));
System.out.println("B:" + getMyName(b));
}
I am using Java-8 default here to implement a default getHeight but it would not take much effort to eliminate that - you would need to implement a getHeight for the getMyName(A) method.
Sadly - of course - this is not using generics in the solution so you may see this as not an answer to your question but it is an alternate solution to your problem so I chose to post.

Json Jackson deserialization without inner classes

I have a question concerning Json deserialization using Jackson.
I would like to deserialize a Json file using a class like this one:
(taken from http://wiki.fasterxml.com/JacksonInFiveMinutes)
public class User
{
public enum Gender { MALE, FEMALE };
public static class Name {
private String _first, _last;
public String getFirst() { return _first; }
public String getLast() { return _last; }
public void setFirst(String s) { _first = s; }
public void setLast(String s) { _last = s; }
}
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() { return _name; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setName(Name n) { _name = n; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
A Json file can be deserialized using the so called "Full Data Binding" in this way:
ObjectMapper mapper = new ObjectMapper();
User user = mapper.readValue(new File("user.json"), User.class);
My problem is the usage of the inner class "Name". I would like to do the same thing without using inner classes. The "User" class would became like that:
import Name;
import Gender;
public class User
{
private Gender _gender;
private Name _name;
private boolean _isVerified;
private byte[] _userImage;
public Name getName() { return _name; }
public boolean isVerified() { return _isVerified; }
public Gender getGender() { return _gender; }
public byte[] getUserImage() { return _userImage; }
public void setName(Name n) { _name = n; }
public void setVerified(boolean b) { _isVerified = b; }
public void setGender(Gender g) { _gender = g; }
public void setUserImage(byte[] b) { _userImage = b; }
}
This means to find a way to specify to the mapper all the required classes in order to perform the deserialization.
Is this possible? I looked at the documentation but I cannot find any solution.
My need comes from the fact that I use the Javassist library to create such classes, and it does not support inner or anonymous classes.
Thank you in advance
There should be no difference between the static inner class Name, and the top-level class of the same name. The Jackson runtime should not be able to meaningfully distinguish between the two situations.
Have you tried moving the Name class out of User, changing it into a top-level class? It should still work as before.
edit: I just tried this, and it works fine when Name is a top-level class. The example had it as an inner class for the sake of brevity, I suspect.
mr. Skaffman's answer is right on. The only additional thing to mention is that unlike JAXB, Jackson does not generally require you to specify classes you operate on, except for the root class (and not always even that, if you use Polymorphic Handling).

Categories

Resources