Hey you people out there,
I'm asking myself the following question. This should be done in Java, but since I don't know how to do it anyway just a concept would help too:
I have the following code:
public abstract class A {
protected enum AType implements AInterface {
A_VALUE
}
public AInterface[] possibleRequests() {
AInterface types = AType.values();
return ArrayUtils.concat(types, possibleFurtherRequests());
}
public abstract AInterface[] possibleFurtherRequests();
}
public class B extends A {
protected enum BType implements BInterface {
B_VALUE
}
#Override
protected AInterface[] possibleFurtherRequests() {
//Here is my problem.
return BType.values();
}
}
public interface AInterface {
}
public interface BInterface extends AInterface {
}
What I want to do is have these possibleRequest-methods in indefinite depth. They should only be accessible via A, I do not and should not know which class the object of type A belongs to.
What I mean by indefinite depth is, that say this concept was extended with C extends B. I now want to access all values from A, B and C. How do I enforce, that whenever a new subclass is added the programmer is forced to define these AInterface-enumerations (optional) and how do I force him to implement a method that is then called recursively up the class Hierarchy (not optional).
I don't need help defining an abstract method, or overriding one. What I want to do is NOT override the existing one and NOT add an abstract method to each inheriting class that gets called.
I honestly don't know how to ask this question but I hope someone out there understands what I mean.
If not leave a comment.
Visibility of the methods is important. You can't force the subclasses to implement the now NOT abstract possibleFurtherRequests, but that is the only method they need. You also can't force them to call the super method either. Code reviews work nicely for that.
protected enum AType implements AInterface {
A_VALUE
}
protected enum BType implements BInterface {
B_VALUE
}
public abstract class A {
final public AInterface[] possibleRequests() {
return possibleFurtherRequests();
}
protected AInterface[] possibleFurtherRequests() {
return AType.values();
}
protected AInterface[] combine(AInterface[] some, AInterface[] more) {
AInterface[] combined = new AInterface[some.length + more.length];
System.arraycopy(some, 0, combined, 0, some.length);
System.arraycopy(more, 0, combined, some.length, more.length);
return combined;
}
}
public class B extends A {
#Override
protected AInterface[] possibleFurtherRequests() {
return combine(super.possibleFurtherRequests(), BType.values());
}
}
public interface AInterface {
}
public interface BInterface extends AInterface {
}
public void test() {
AInterface[] result = new B().possibleRequests();
Stream.of(result).forEach(System.out::println);
}
And the result is
A_VALUE
B_VALUE
Related
I am in a situation as follows.
I have an interface A which is inherited by class B,C,D (B,C,D implements A).
public interface A{
public String someMethod();
}
class B implements A{
ObjectType1 model;
#Override
public String someMethod(){
if(model instanceof X){
System.out.print(true);
}
}
}
class C implements A{
ObjectType2 model;
#Override
public String someMethod(){
if(model instanceof X){
System.out.print(true);
}
}
class D implements A{
ObjectType3 model;
#Override
public String someMethod(){
if(model instanceof X){
System.out.print(true);
}
}
As you can see all method implementations are the same. So I am duplicating code. My plan was to move the method to A and make A an abstract class. But the problem is my method depends on the model field. So what would be my options to make this code better?
bdw class A,B,C extends and implements other classes too.
EDIT
modification in code. check field
I don't see any problem related to the model field transforming the interface A into an abstract class.
There is no need to reimplement the method in the subclasses if it is the same, unless you want to change its behavior (override it).
public abstract class A {
// Make it protected so it can accessible by subclasses
protected Object model;
// Common behavior that will be inherited by subclasses
public String someMethod() {
if (model instanceof X) {
return "x";
} else {
return "not x";
}
}
}
public class B extends A {
// Subclasses may access superclasses fields if protected or public.
public void someOtherMethod() {
System.out.println(super.model.toString());
}
}
public class C extends A {
// You may wish to override a parent's method behavior
#Override
public String someMethod() {
return "subclass implements it different";
}
}
For your new code example, if you really want to do that in a procedural way you can create an abstract superclass ObjectType and then it will be accessible for the parent as well.
However I wouldn't do that. It seems to me that in doing so is the very opposite of what object orientation tries to solve.
By using a subclass to define the behavior, you wouldn't need to do it in a procedural logic. That's precisely then point of using objects, inheritance and overriding/implementing behavior as needed.
Create a parent class A with said field, and said function. Have the other classes extend A. No need to override them if they function the same.
To deduplicate, you can either make A an abstract class and move the implementation of the method and the field there, or create an abstract class, say E, that implements the interface with that method and field and then have B, C and D extend that class E.
For the more general question of depending on a subclass's field, you can create an abstract method getModel which the subclasses decide how to implement -- by returning a model field or doing something else.
If you are using java 8 you could use default method in interface A, with a getter method for model.
public interface A{
default public String someMethod() {
if(getModel() instanceof X){
System.out.print(true);
}
}
public Object model getModel();
}
Then implement getModel method in all child interfaces.
If you're going to do this you must have model to be of the same (basic) type in all derived objects. If it were of the same type there's a case for putting the model to a base class. Anyway if they are of different derived types you would need to have an accessor to get it.
interface B {
BaseModel getModel();
default public strict doSomething() {
BaseModel m = getModel();
// do something with m
}
}
class D implements B {
DerivedModel model;
public getModel() {
return model;
}
}
If I was given a chance to refactor it, I will follow below approach, leveraging Java 8 Default Methods:
interface A {
default String someMethod(X objectType) {
if (objectType instanceof X) {
System.out.println(true);
}
// return something, for now returning class
return objectType.getClass().toString();
}
}
class B implements A {
#Override
public String someMethod(X objectType) {
if (objectType instanceof X) {
System.out.println(true);
}
// return "Hello"
return "Hello";
}
}
class C implements A {}
class D implements A {}
Usage:
public class Main implements A {
public static void main(String[] args) {
B b = new B();
C c = new C();
D d = new D();
Main main = new Main();
main.call(b);
main.call(c);
main.call(d);
}
public void call(A clazz) {
ObjectType1 objectType1 = new ObjectType1();
String type = clazz.someMethod(objectType1);
System.out.println(type);
}
}
interface X {
}
class ObjectType1 implements X {
}
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.
Let's say I have following interface:
interface Mammal {
void marry(Mammal m);
Mammal giveBirthTo();
}
However, this doesn't say quite exactly what I want.
Obviously, a human can't marry a dog, nor give birth to a cat. So how can I embed this information into the interface, such that the input type and output type can be changed automatically as it gets implemented?
You could use generics and change your design.
Something in the lines of:
interface Marriable<T extends Mammal> {
void marry(T sweetHalf);
T giveBirthTo();
}
... where Mammal is your top interface or abstract class, and Human, Dog, Unicorn etc. extend / implement it.
You can generify your interface using a recursive type variable:
interface Mammal<T extends Mammal<T>> {
void marry(T m);
T giveBirthTo();
}
This way, the Java compiler can give you a certain validation level. Notice however that this approach is still open to abuse. For example:
class Cat implements Mammal<Cat> {
#Override void marry(Cat cat) { ... }
#Override Cat giveBirthTo() { ... }
}
class Dog implements Mammal<Cat> { // implements wrong interface
#Override void marry(Cat cat) { ... }
#Override Cat giveBirthTo() { ... }
}
The compiler can only assure that you implement the Mammal interface by some sub type of the same interface, but not by the particular class that implements it. This latter type constraint cannot be expressed in the Java programming language.
Generics. Try with
private static interface Race {
}
private static class Human implements Race {}
private static class Canine implements Race {}
private static interface Being<R extends Race> {
void marry(Being<R> other);
Being<R> giveBirthTo();
}
private void tryMe() {
Being<Human> aHuman = new Being<Human>() {
#Override
public void marry(Being<Human> other) {
}
#Override
public Being<Human> giveBirthTo() {
return null;
}
};
Being<Canine> aCanine = new Being<Canine>() {
#Override
public void marry(Being<Canine> other) {
}
#Override
public Being<Canine> giveBirthTo() {
return null;
}
};
aHuman.marry(aCanine); // not possible
}
It is possible to narrow return type in overriding methods in Java.
But is it possible to force this narrowing during declaration?
For example, this may be good in the pattern, where inner class is subclassed simultaneously with outer one:
public class Try_ForceNarrow {
public interface IMember {
}
public interface Container<M extends IMember> {
M createMember();
}
public static class A implements Container<A.Member> {
#Override
public Member createMember() {
return new Member();
}
public class Member implements IMember {
}
}
public static class B extends A implements Container<B.Member> {
#Override
public Member createMember() {
return new Member();
}
public class Member extends A.Member {
}
}
public static void main(String[] args) {
}
}
This code fails compile with an error of "The interface Container cannot be implemented more than once with different arguments".
How to avoid this?
Of course, I can just write
public static class B extends A {
#Override
public Member createMember() {
return new Member();
}
public class Member extends A.Member {
}
}
But this way I can forget to override createMember() and violate the pattern.
And what about A<T> implements Container<T> ? You can restrict T further as you wanted...
It appears to me that you want each subclass C to have a createMember factory method that returns a new object that has the same type. The problem is that if C1 provides a factory method that returns C1, and then C2 extends C1, there's no way to force C2 to provide its own method--it could just inherit the one from C1.
I don't think there's a solution that will catch errors at compile time, but maybe you can do something that catches the error at run time:
abstract class MemberBase {
protected abstract MemberBase doCreateMember();
protected abstract Class<?> memberClass();
public MemberBase createMember() {
MemberBase result = doCreateMember();
if (result.getClass() != memberClass()) {
throw new RuntimeException("createMember returned the wrong class");
}
return result;
}
}
public static class A extends MemberBase {
#Override
protected Member doCreateMember() {
return new Member();
}
#Override
protected Class<?> memberClass() {
return Member.class;
}
public class Member implements IMember {
}
}
public static class B extends A {
// If you forget to define this, the doCreateMember in A will be
// inherited, but it will return the wrong class and lead to a
// run-time exception
#Override
protected Member doCreateMember() {
return new Member();
}
#Override
protected Class<?> memberClass() {
return Member.class;
}
public class Member extends A.Member {
}
}
I haven't tested this, and I'm not sure it accomplishes what you are looking for. Plus I may have gotten some syntax wrong. But maybe this, or a modification of it, might be useful.
I believe this fulfills what you are trying to do.
You can create a new abstract class that implements Container which allows you to continually extend or narrow the generics, but you need to declare each class static:
class Try_ForceNarrow {
public interface IMember {
}
public interface Container<M extends IMember> {
M createMember();
}
//The abstract class that lets you continually extend or "narrow"
public static abstract class A<E extends A.Member> implements Container<E> {
public static class Member implements IMember {
}
}
//Here is the first class that extends the Abstract Class A
public static class B extends A<B.Member> { //This class now Implements Container<B.Member>
#Override
public Member createMember() {
return new Member();
}
//Since this is the first extension we will extend A.Member
public static class Member extends A.Member {
}
}
//This is an additional class that extends A but we want to extend the functionality of B.Member also.
public static class C extends A<C.Member> { //This class now Implements Container<C.Member>
#Override
public Member createMember() {
return new Member();
}
//C.Member properly extends B.Member
//if this class is going to be extended this needs to be static
public class Member extends B.Member {
}
}
}
And of course per your requirements if you remove
#Override
public Member createMember() {
return new Member();
}
From the extending sub-classes you get a compile error.
Of course it will fail, your class A implements Container<A.Member>, but your class B extends A but also implements Container<B.Member> which is like class B extends A implements Container<A.Member> Container<B.Memeber> , and in terms of the compiler, there is no difference between Container<A.Member> and Container<B.Member> due to type erasure, after compilation, all generics information will be lost, so there is no <……> after type erasure, only their upper bounds and lower bounds exist, your type parameters are unbounded so they will erase to the same type, after erasure, your class B literally looks like this class B extends A implements Container Container which is fundamentally wrong. You can narrow the return type on overrides which is called covariant return type, this will also create a bridge method in the VM to preserve porlymorphism in Generics.
Class A derives from abstract class B and implements the abstract method foo.
Now in method foo I want to do something which depends on a member variable of class A, mType. However this results in a bug because foo is called in the constructor from abstract class B, hence mType isn't initialised yet.
It is not possible to initialise mType before the super() so I don't know a good and clean way to go about this. Of course I can make mType a member of B but I think this isn't a good way to go because mType doesn't have anything to do with this class, in this example this is perhaps not clear, but of course I've rewritten the practical situation to a short simple one in order to explain the problem.
What is a good way to tackle this problem?
public abstract class B {
public B() {
foo(); // A::mType IS NOT INITIALISED!!
}
protected abstract void foo();
}
private class A extends B {
public enum Type { TYPE1, TYPE2 };
public A(Type aType) {
super();
mType = aType;
}
#Override
protected void foo() {
if (mType == Type.TYPE1) {
// ..
} else {
// ...
}
}
}
Agreeing on the comment made by Seelenvirtuose, I'm going answer my question. It is indeed bad practice to call overridable methods in the constructor. The following solves the problem:
public abstract class B {
public B() { }
protected abstract void foo();
protected void init() {
foo();
}
}
private class A extends B {
public enum Type { TYPE1, TYPE2 };
public A(Type aType) {
super();
mType = aType;
init();
}
#Override
protected void foo() {
if (mType == Type.TYPE1) {
// ..
} else {
// ...
}
}
}
At first sight it may perhaps seem impractical, why not simply call foo in the constructor of class A. But in my real practical situation it is rather more complex, various overrided methods need to be called in a certain sequence. The base class needs to provide a method for this in order to avoid code duplication. Adding a simple init method which is called from the derived class tackles this problem.