at work we do a peer review of code and I found something I don't like and I want to ask about best practice for this particular problem.
We have an interface:
public interface Item {
public String getType();
//some other methods
}
and an implementing class:
public class EmailItem implements Item {
public static final String TYPE = "email";
#Override
public String getType() {
return TYPE;
}
}
and some code that uses the classes:
for (Item item : items) {
if (EmailItem.TYPE.equals(item.getType())) {
isProcessed = Processor.process(item);
} else {
LOGGER.error("Unknown failover type received to process. Type: {}", item.getType());
}
}
At this point we have only one implementing class so checking the type is not necessary but we will add some other implementations and then it would make sense (though switch will be used).
The main issue is that EmailItem has variable TYPE set as public and this variable has also a getter.
Both class and instance of that class should have access to this variable, but having it public static final and accessing it with instance directly doesn't seem right/best practice (although it is technically possible) and when it would be private (as it should) then it won't be accessible from other classes (where for cycle is and static would not make sense at that point).
Through discussion we come up with solution with usage of instanceOf(...) or instance.getClass().getName() and EmailItem.class.getName() but none of them seem elegant to me :).
So finally, my question is what is the most elegant solution for described problem?
Heh, this is my first question here and I hope it makes sense to you ;).
Thinking about it from an OO point of view I'd consider the following approach:
public interface Item {
public boolean process();
//some other methods
}
public class EmailItem implements Item {
#Override
public boolean process() {
// email specific implementation
}
}
public class AnotherItem implements Item {
#Override
public boolean process() {
// another implementation
}
}
for (Item item : items) {
isProcessed = item.process();
}
The way you did it is fine, if you want to do it that way:
The static final variable TYPE lets you treat it as a type constant,
The implementation on the instance lets you check the constant against the return value on the interface.
However, when you find yourself dispatching on a type represented by String or some other value, you are usually going down a wrong path of switch statements in object-oriented code. If you have a choice of action at this point, consider an alternative technique of double dispatch, such as implementing the Visitor Pattern:
interface ItemVisitor {
void visitEmail(EmailItem item);
void visitSms(SmsItem item);
}
interface Item {
void accept(ItemVisitor v);
}
class EmailItem implements Item {
public void accept(ItemVisitor v) { v.visitEmail(this); }
}
class SmsItem implements Item {
public void accept(ItemVisitor v) { v.visitSms(this); }
}
Now you can do this:
class Example implements ItemVisitor {
public void visitEmail(EmailItem item) {
// Do something with an e-mail
}
public void visitSms(SmsItem item) {
// Do something with an SMS
}
public static void main(String[] args) {
Example e = new Example();
for (Item item : ItemSource.getManyItems()) {
item.accept(e);
}
}
}
If all "types" for your Item are known at compile time, you could use an enum like this:
public interface Item {
enum ItemType { MAIL, OTHER; }
public ItemType getType();
//some other methods
}
Related
I came across this code in an exercise for declaring an abstract class:
import java.util.ArrayList;
public abstract class Box {
public abstract void add(Item item);
public void add(ArrayList<Item> items) {
for (Item item : items) {
Box.this.add(item);
}
}
public abstract boolean isInBox(Item item);
}
I am not able to understand what the add(ArrayList<Item> item) method does. I get it that it loops through an ArrayList called items but what does Box.this.add(item) do?
Can someone clarify this?
On top of what #ernest_k wrote in a comment there is an actual use-case where you actually need to qualify a method call with the class name like this: If you create an anonymous inner class in a method that accesses fields of its outer class, like the following arbitrary (and quite useless in reality) example:
import java.util.ArrayList;
public abstract class Box {
public abstract void add(String item);
public void add(ArrayList<String> items) {
for (String item : items) {
Runnable r = new Runnable() {
#Override
public void run() {
add(item); // works, implicitly accesses Box.this.add
this.add(item); // does not work as "add" is not a method of the anonymous runnable
Box.this.add(item); // works
}
};
r.run();
}
}
public abstract boolean isInBox(String item);
}
That class is declaring an interface with some code already in. Specifically, it is declaring a Box without a detailed implementation, in which you can later create the Box with the underlying code that suits your needs.
For example, you can declare the BoxOnSet class, that implements that declaration with a HashSet<>:
public abstract class BoxOnSet extends Box {
public BoxOnSet()
{
this.items = new HashSet<>();
}
public void add(Item item)
{
this.items.add( item );
}
public boolean isInBox(Item item)
{
return this.items.contains( item );
}
private HashSet<Item> items;
}
As for your specific question, the add(ArrayList<>) method is equivalent to the collections addAll() method. It just uses the abstract add(Item) in order to insert items in the Box. You can specify add( item ), this.add( item ) or even Box.this.add( item ), and in this example all point to the same method, they are just ways to specify further.
I have two exact the same functions and one different function which take a TypeX as parameter. All TypeX has the same parent class Type. The dummy code is like:
public void Append(TypeA item) { //same code }
public void Append(TypeB item) { //same code }
public void Append(TypeC item) { //different code }
I wonder is there a good way to optimize such functions? My code needs to pick up the right function based on the class type, so I can't use the parent class or a generic type here because that will affect TypeC's engagement.
The best thing would be public void Append(TypeA item || TypeB item) but of course there's no such a thing available. Any idea?
Whereas the solutions offered by #erwin-bolwidt would work, I suggest you also consider
private void baseAppend (TypeParent item) { //same code }
public void Append(TypeA item) { baseAppend (item); }
public void Append(TypeB item) { baseAppend (item); }
public void Append(TypeC item) { //different code }
This method would allow a looser coupling and the potential for specialised logging and expansion in the future
Methods to be called are selected at compile time based on the declared type (not the actual type) of the object. It's safe to merge Append for TypeA and TypeB into one method that takes an argument of Type item - it doesn't make a difference from the current code.
But if you want to select on actual type, you need to use instanceof. Or you create a method on type that returns whatever you need in the append method.
public void append(Type item) {
if (item instanceof TypeC) {
// Do TypeC-specific stuff
} else {
// Do stuff for TypeA, TypeB, and any other subtype of Type
}
}
Or cleaner, if the only difference is in what you get from the item:
public class Type {
public X getWhateverYouWantToAppend() {
// Return stuff for TypeA, TypeB, and any other subtype of Type
}
}
public class TypeC extends Type {
public X getWhateverYouWantToAppend() {
// Return stuff for TypeC specifically
}
}
public class YourOtherClass {
public void append(Type item) {
X thingToAppend = item.getWhateverYouWantToAppend();
// Do the appending
}
}
You can create a parent class for TypeA and TypeB. Then use this type as an argument to the overloaded function.
This way you can avoid a duplication of code.
Another way is to let these classes to implement some interface then use this interface as an argument to the overloaded function.
Third, you can use generic type and delegate implementation to corresponding functions.
its simple in java, you can do it using method overloading
public class example{
public static void print(String s) {
System.out.println("string - "+s);
}
public static void print(int q) {
System.out.println("number - "+q);
}
public static void main(String[] args) {
print(12);
print("welcome");
}
}
output
number - 12
string - welcome
I am way over thinking this: What I am trying to do is [hopefully not reinvent the wheel and] come up w/ a [Android] Java eventing mechanism that allows subclasses to pre-define an arbitrary set of "features" with getters and setters that fire individual callbacks.
I think I am fusioning some combination of Command, Visitor, Decorator, Facade and Observer patterns here, and confusing myself along the way.
I have been programming for well over 20 years, but I feel like a n00b on this fairly simple problem! :(
I have searched SO for the compiler error and read many of the results, but I still haven't found a solution that works for me.
(How to make a Java class that implements one interface with two generic types? seems to be the most relevant one that I have found, but I also want to generically get the values and fire events to callbacks when they are set).
First, let the below mostly valid code speak for itself...
interface IFeature
{
}
interface IFeatureCallbacks<T extends IFeature>
{
boolean onChanged(Feature<T> c);
}
public static class Feature<T extends IFeature>
{
private Set<IFeatureCallbacks<T>> listeners = new LinkedHashSet<>();
public void addListener(IFeatureCallbacks<T> listener)
{
listeners.add(listener);
}
public void removeListener(IFeatureCallbacks<T> listener)
{
listeners.remove(listener);
}
protected void onChanged()
{
for (IFeatureCallbacks<T> listener : listeners)
{
listener.onChanged(this);
}
}
}
//
interface IFeatureA
extends IFeature
{
int getA();
}
interface IFeatureACallbacks
extends IFeatureCallbacks<IFeatureA>
{
}
public static class FeatureA
extends Feature<IFeatureA>
implements IFeatureA
{
private int a;
public void setA(int value)
{
a = value;
onChanged();
}
#Override
public int getA()
{
return a;
}
}
//
interface IFeatureB
extends IFeature
{
boolean getB();
}
interface IFeatureBCallbacks
extends IFeatureCallbacks<IFeatureB>
{
}
public static class FeatureB
extends Feature<IFeatureB>
implements IFeatureB
{
private boolean b;
public void setB(boolean value)
{
b = value;
onChanged();
}
#Override
public boolean getB()
{
return b;
}
}
//
interface IDeviceWithFeatureA
extends IFeatureA
{
}
interface IDeviceWithFeatureACallbacks
extends IFeatureACallbacks
{
}
public static class DeviceWithFeatureA
extends Feature<IDeviceWithFeatureA>
implements IDeviceWithFeatureA
{
FeatureA a = new FeatureA();
public void addListener(IDeviceWithFeatureACallbacks listener)
{
a.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
}
//
interface IDeviceWithFeatureB
extends IFeatureB
{
}
interface IDeviceWithFeatureBCallbacks
extends IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureB>
implements IDeviceWithFeatureB
{
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureBCallbacks listener)
{
b.addListener(listener);
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
The above code seems to work fine, albeit something about it smells a bit off.
The problem is when I try to do this:
interface IDeviceWithFeatureAAndFeatureB
extends IFeatureA, IFeatureB
{
}
/*
Compiler error:
'IFeatureCallbacks' cannot be inherited with different type arguments 'IFeatureA' and 'IFeatureB'
*/
interface IDeviceWithFeatureAAndFeatureBCallbacks
extends IFeatureACallbacks, IFeatureBCallbacks
{
}
public static class DeviceWithFeatureAB
extends Feature<IDeviceWithFeatureAAndFeatureB>
implements IDeviceWithFeatureAAndFeatureB
{
FeatureA a = new FeatureA();
FeatureB b = new FeatureB();
public void addListener(IDeviceWithFeatureAAndFeatureBCallbacks listener)
{
a.addListener(listener);
b.addListener(listener);
}
public void setA(int value)
{
a.setA(value);
}
#Override
public int getA()
{
return a.getA();
}
public void setB(boolean value)
{
b.setB(value);
}
#Override
public boolean getB()
{
return b.getB();
}
}
I am less interested in trying to figure out how to make what I am trying to do compilable, and I am more interested in what about my abuse of a pattern is way off base so that I can re-write it to be both simpler and compile.
You are abusing the basic "pattern" of OOP -- inheritance. The adage is that "favor composition over inheritance". Think in terms of "contains", instead of "is-a".
Take Zoo for example. A zoo is just a bunch of animals, right? So naturally, we may want to declare Zoo as subtype of Set<Animal>. Perhaps even have class Zoo extends HashSet<Animal>.
However, that is likely a wrong design. A zoo is actually a lot of things. It contains a set of animals, sure; but it also contains a set of people (as workers, not exhibits (although...) ). So it's better to
class Zoo
Set<Animal> animals(){ ... }
Set<Person> workers(){ ... }
Anywhere we need to treat a zoo as a set of animals, just use zoo.animals(); think of it as a type cast, or projection. We don't need inheritance here.
In your design, you have too many types; what's worse, too many type relationships. It seems that you simply need one generic class that reads/writes value of T, and contains listeners of T
class Feature<T>
T value;
// getter
// setter
Set<ChangeListener<T>> listeners;
interface ChangeListener<T>
void onChange(T oldValue, T newValue)
A device contains a bunch of features
class SomeDevice
Feature<Integer> featureA = new Feature<>();
Feature<Boolean> featureB = new Feature<>();
That's it. You can operate on feature A of the device by operating on itsfeatureA.
I frequently find myself wanting to write generic class definitions of the form
public class Foo<ActualType extends Foo<ActualType>>
For example in a setup like this:
public interface ChangeHandler<SourceType> {
public void onChange(SourceType source);
}
public class Foo<ActualType extends Foo<ActualType>> {
private final List<ChangeHandler<ActualType>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<ActualType> handler) {
handlers.add(handler);
}
#SuppressWarnings("unchecked")
protected void reportChange() {
for (ChangeHandler<ActualType> handler: handlers)
handler.onChange((ActualType) this);
}
}
public class Bar extends Foo<Bar> {
// things happen in here that call super.reportChange();
}
public static void main(String[] args) throws IOException {
Bar bar = new Bar();
bar.addChangeHandler(new ChangeHandler<Bar>() {
#Override
public void onChange(Bar source) {
// Do something with the changed object
}
});
}
The change-event here is just an example. This is more of a general problem that I'm having whenever I would like to allow a super-class to provide functionality that is "individualized" to each specific sub-class (not sure how to phrase this better... in the example above the "individualization" is the fact that the ChangeHandler is called with an object of the actual sub-type (Bar) not with the type of the super-class (Foo) that is calling the handler).
Somehow this approach seems a bit messy to me. And it actually allows for potential issues since nothing prevents me from then defining:
public class Baz extends Foo<Bar> { /* ... */ }
Is there a cleaner alternative?
The holy grail would be some type parameter that is always defined to contain the current class, like a static version of this.getClass() that would allow me to write something like this instead:
public class Foo {
private final List<ChangeHandler<this.Class>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<this.Class> handler) {
handlers.add(handler);
}
protected void reportChange() {
for (ChangeHandler<this.Class> handler: handlers)
handler.onChange(this);
}
}
Where this.Class would be equal to Bar for classes of type Bar.
It is a really abstract problem. In my opinion the short answer to "how to make this cleaner" is: only use generics where it is needed.
public class List<T extends List<T>>
What is this trying to express (substituted)? A list which only allows to hold (T extends) other lists which themselves hold Ts (List) which as we know from before are Lists which only allow to hold ... and so on. Kind of circular, I don't see how you would end up with something like that?
public interface ChangeHandler<SourceType> {
public void onChange(SourceType source);
}
Why do you want to use generics here? If you want to have a change handler which can handle several resource types, then you can either create a super class from which all actual sources inherit or you create an interface which is implemented by the sources. Like that you can exactly specify what is exposed by the sources. Alternatively the source can create a source object when notifying instead of passing "this" (then it is more like a message). For example:
public interface ChangeHandler {
public void onChange(Source source);
}
public abstract class Source {
private List<ChangeHandler> handlers;
protected int nr;
public Source(int nr) {
this.nr = nr;
}
public abstract Something getSomething();
public String toString() {
return "SRC" + nr;
}
...
private notify(int index) {
handlers.get(i).onChange(this);
}
}
public class Foo extends Source {
public Foo(int nr) {
super(nr);
}
public String toString() {
return super.toString() + "Foo";
}
public Something getSomething() {
return new Something();
}
}
You never need to cast... or do you? I'm not sure if I understand the problem.
I would recommend that we simply use <This> to represent the "self type". No need for bound, since it looks complicated, doesn't deliver the intention, and cannot enforce the constraint anyway.
public class Foo<This> {
private final List<ChangeHandler<This>> handlers = new ArrayList<>();
public void addChangeHandler(ChangeHandler<This> handler) {
handlers.add(handler);
}
#SuppressWarnings("unchecked")
protected void reportChange() {
for (ChangeHandler<This> handler: handlers)
handler.onChange( (This)this );
}
}
Notice the cast (This)this.
See also Java generics: Use this type as return type?
I never use type parameters to pass "ActualType" because then it is impossible to extend the object:
public class Bar extends Foo<Bar> {
// things happen in here that call super.reportChange();
}
public class Bar2 extends Bar{
// ...
}
Bar2 "ActualType" is still Bar, and there is nothing you can do: you won't be able to use ChangeHandlers for Bar2
To avoid the issue, the only possible fix I see is to delegate the cast operation to an other class (you could also use a default method in the ChangeHandler interface).
Here is a possibility:
public class Foo // no more type parameter
{
private final List<FooCaster<?>> casterHandlers = new ArrayList<>();
/**
* unsafe because you could register a ChangerHandler of any type.
* worst of all, everything is unchecked cast so the error could show up late.
*/
public <T> void addChangeHandler(ChangeHandler<T> handler) {
casterHandlers.add(new FooCaster<T>(handler));
}
protected void reportChange() {
for (FooCaster<?> caster: casterHandlers) {
caster.reportChange(this);
}
}
class FooCaster<T> {
protected ChangeHandler<T> ch;
protected FooCaster(ChangeHandler<T> ch) {
this.ch = ch;
}
#SuppressWarnings("unchecked")
public void reportChange(Foo f) {
ch.onChange((T)f);
}
}
}
Personnaly in the case of broadcasting changes to listener/changehandlers, I'm enclined to externalize the process to an other class, which makes it possible to use parameter types properly and avoid unsafe casts.If you are still willing to use reportChange() from within the foo object, here is a possible implementation (otherwise you could store a T reference in the Broadcaster).
public class Broadcaster<T extends Foo> {
protected final List<ChangeHandler<? super T>> changeHandlers;
public Broadcaster() {
this.changeHandlers = new ArrayList<>();
}
public void startListeningTo(T obj) {// only T type objects are accepted
obj.registerBroadcaster(this);
}
public void addChangeHandler(ChangeHandler<? super T> changeHandler) {
changeHandlers.add(changeHandler);
}
void reportChange(Foo obj) {
T o = (T)obj;
for(ChangeHandler<? super T> c : changeHandlers) {
c.onChange(o);
}
}
}
public class Foo {
private final List<Broadcaster<?>> broadcasters = new ArrayList<>();
// cannot be accessed from outside of the package, only Broadcaster.startListeningTo(T o) can be used
final void registerBroadcaster(Broadcaster<?> b) {
broadcasters.add(b);
}
public final void reportChange() {
for (Broadcaster<?> b: broadcasters) {
b.reportChange(this);
}
}
}
public class Bar extends Foo {
// things happen in here that call super.reportChange();
}
public static void test() {
Broadcaster<Bar> broadcaster = new Broadcaster<>();
broadcaster.addChangeHandler(new ChangeHandler<Bar>() {
#Override
public void onChange(Bar obj) {
// do something
}
});
//note that you can use the same broadcaster for multiple objects.
Bar b = new Bar();
broadcaster.startListeningTo(b);
b.reportChange();
}
Note that you will not be able to add changeHandlers from within Bar (but is it really the object's job to register changeHandlers for itself?).
I'm looking for a way to be able to define a method for each enum instance. We all know about the code construction at the bottom of this page.
The difference I'm looking for is to be able to define one or more abstract methods for each enum in a separate file that is verified compile-time. Meaning if someone were to add another enum instance I would get a compile-time error and not a run-time error which is what I get with the construction at the bottom of this page.
The reason for the request is that in some code I'm looking at there are many methods that should be defined per enum but are really unrelated to the enum definition so I'd like to place them in separate files but not lose the benefits of the "standard" way of solving this.
public enum MyEnum {
X {
public void calc(Outer o) {
// do something
}
},
Y {
public void calc(Outer o) {
// do something
}
};
// abstract method
abstract void calc(Outer o);
}
Consider the folowing code:
interface Delegate{
void calc();
}
enum TestEnum {
EnumValue1(new Delegate() {
#Override
public void calc() {
}
}),
EnumValue2(new Delegate() {
#Override
public void calc() {
}
});
private Delegate delegate;
TestEnum(Delegate d){
this.delegate = d;
}
public Delegate getDelegate() {
return delegate;
}
}
public class Test {
public static void main() {
TestEnum.EnumValue1.getDelegate().calc();
TestEnum.EnumValue2.getDelegate().calc();
}
}
You cannot define methods for classes outside of a class!
You could define a callback interface that each enum instance had to have an instance of:
public interface MyEnumCallback {
doStuff(final Outer o)
}
Then your enum would look something like
public enum MyEnum {
X(new XCallback()),
Y(new YCallbaxk());
private final MyEnumCallback callback;
public MyEnum(final MyEnumCallback callback) {
this.callback = callback;
}
public <Whatever> call(final Outer o) {
callback.doStuff(o);
}
}
This separates your Enum from the methods as you wanted - it would also throw a compile time error if someone didn't provide an implementation of MyEnumCallback to the constructor of the Enum instance.