I don't know why I can't find an answer to this online.
I have classes that implement multiple methods and I would like to write methods to expect them. I don't know how to do it though or if it's even possible.
E.g:
public void yellAtPet(<? extends Pet implements YellableAt> arg) {
arg.yellAt("Don't go there!");
arg.pet("Good Boy");
}
Extends is used for both interfaces and parent classes.
If you want to inforce multiple extends you needs something like:
<T extends ClassA & InterfaceB>
To enforce this on a method, generify the class:
public class MyClass<T extends something & somethingelse>{
public void doSomething(T arg)
{
//call methods defined by either interface
}
}
This should work fine as a generic method, without making your entire class generic:
public <T extends Pet & YellableAt> void yellAtPet(T arg) {
arg.yellAt("Don't go there!");
arg.pet("Good Boy");
}
Related
I'm pretty new to Java and it's safe to say I'm just taking my first steps. So I'm sorry if the question is a little awkward.
Basically I would like to know what would be the best approach to solving the issue I have.
I've got an abstract class BasePage and HomePage that is supposed to be derived from the former. All pages can be loaded, so it makes sense to define the load method on the BasePage, but I would like the method to return the type of HomePage in this case and SubClass type in general.
From what I've learnt , seems like it's not that easy and I started to think maybe it's because it's a flawed design.
I also have a few methods that are valid for all pages, one of them is confirmAge, cos no matter what page you go to, you're always greeted with the age gate and basically you have to confirm you're above 18 to proceed. So since it's something fundamental, I believe it should be coded into the BasePage.
Anyway, no matter what I use - abstract classes or interfaces, I have the same issue with return type and I would really like to enforce some interface on all the classes derived from BasePage.
Any help would be appreciated.
Simplest way addressing your use-case - relying on covariant return types
Example:
public abstract class BasePage {
public abstract BasePage load();
}
public class HomePage extends BasePage {
#Override
public HomePage load() {
//...
return this;
}
}
If you require also polymorphic arguments in addition to return types - make use of generics
Example:
public abstract class BasePage <T extends BasePage<T>> {
public abstract T load();
public abstract void copyFrom(T another);
}
public class HomePage extends BasePage<HomePage> {
#Override
public HomePage load() {
//...
return this;
}
#Override
public void copyFrom(HomePage another) {
//...
}
}
Note, that second <T> in the generic definition can be omitted, giving a shorter
class BasePage <T extends BasePage>
and in this case, compiler will infer
class BasePage <T extends BasePage<?>>
which is still suitable for your general case
You can add the actual Type as a type parameter for the BasePage:
public abstract class BasePage<T extends BasePage<?>> {
public abstract T load();
}
public class HomePage extends BasePage<HomePage> {
#Override
public HomePage load() {
return new HomePage();
}
}
One solution is to use generics:
public abstract class SuperClass<T extends SuperClass<T>> {
protected abstract T someMethod();
}
public class SubClass extends SuperClass<SubClass> {
protected SubClass someMethod() {
return this;
}
}
Generics is best option here. You can T type interface here. Here is an example:
public interface Service<T> {
T execute();
}
public class MyService implements Service<String> {
private final String input1;
private final int input2;
public MyService(String input1, int input2) {
this.input1 = input1;
this.input2 = input2;
}
#Override
public String execute() {
return String.format("'%s%d'", input1, input2);
}
}
I would design it like this: Create an abstract class BaseClass and leave the loadPage method unimplemented (abstract method). Now, whatever classes extend from BaseClass can have their own implementations of loadPage.
Or, write a basic loadPage method in the base class. This method should contain operation like making a GET request, that should be common to all classes whose objects require loading pages. Then, in the sub-classes of the base class, create some method like: homePageLoader. This method can call pageLoader in the base class to make GET requests.
I have a base abstract class PipelineStage which has the following definition:
public abstract class PipelineStage<I, O> implements Runnable {
...
public abstract O step(I input);
...
}
I then have numerous concrete pipeline stages with definitions such as:
public class ConcreteStage extends PipelineStage<InputContextClass, OutputContextClass> {
...
#Override
public OutputContextClass step(InputContextClass input) {
input.someMethod();
...
return new OutputContextClass();
}
...
}
However, this has led to a rigid design in which either:
The context classes are very tightly coupled to which stages they are used in.
Every stage needs to have two full interfaces defined, defining all the properties of the input and output classes.
I wanted to improve this design by having generic interfaces that specify properties of the context classes, the ConcreteStage would then specify what interfaces it's input and output context classes must extend.
However, I can't figure out how to do this in a way the compiler likes.
For example:
public class ConcreteStage extends PipelineStage<I extends Interface1 & Interface2,
O extends Interface2 & Interface3> {
...
#Override
public O step(I input) {
input.someMethodFromInterface1();
input.someMethodFromInterface2();
...
// OutputContextClass extends Interface2 & Interface3
return new OutputContextClass();
}
...
}
However, this doesn't compile, showing that class I needs to be imported.
A wildcard also doesn't work, saying No wildcard expected.
Does anyone have any suggestions on how to implement this in a neat, flexible way? Many thanks in advance!
You need to put the type variable declarations on the class, not the superclass:
public static class ConcreteStage<
I extends Interface1 & Interface2, O extends Interface2 & Interface3>
extends PipelineStage<I, O> {
You can also make an interface uniting input interfaces together interface InputInterface12 extends InputInterface1, InputInterface2 {} and then class ConcreteStage extends PipelineStage<InputInterface12, OutputInterface12> {...}.
Let's say that I have an interface, and all classes that implement that interface also extend a certain super class.
public class SuperClass {
public void someMethod() {...}
}
public interface MyInterface {
void someOtherMethod();
}
//many (but not all) sub classes do this
public class SubClass extends SuperClass implements MyInterface {
#Override
public void someOtherMethod() {...}
}
Then if I'm dealing with an object of type MyInterface and I don't know the specific sub class, I have to hold two references to the same object:
MyInterface someObject = ...;
SuperClass someObjectCopy = (SuperClass) someObject; //will never throw ClassCastException
someObjectCopy.someMethod();
someObject.someOtherMethod();
I tried making the interface extend the super class, but it's a compiler error:
public interface MyInterface extends SuperClass {} //compiler error
I also thought of combining the interface and the super class into an abstract class like so:
public abstract class NewSuperClass {
public void someMethod();
public abstract void someOtherMethod();
}
But then i can't have a sub class that doesn't want to implement someOtherMethod().
So is there a way to signify that every class that implements an interface also extends a certain class, or do I have no choice but to carry around two references to the same object?
I think that the only solution you have would be to have a reference to both, but this indicates that you have a design flaw somewhere. The reason I say is because you should think of an interface as something that your implementing classes will always need. For example, a Car and Airplane both need a Drive() interface. A design reconsideration is probably worth your time. However, if you still want to follow that path, you can do the following:
public class ClassA {
public void methodA(){};
}
public abstract class ClassB extends Class A{
public void methodB();
}
After you have the above setup, you can now reference an object that has the two methods by doing the following:
ClassB classB = new ClassB();
classB.methodA();
classB.methodB();
Now you don't actually have to actually use two pointers to the same object.
I'm trying to understand how to use generics in the form of a bounded type parameter in an interface. In this case, to avoid casting when using the bounded param in concrete implementations but I'm running into an issue. I will use the following example to illustrate my problem:
There's an interface and two concrete implementations
public abstract class Publication {
}
public class Newspaper extends Publication {
}
public class Newspaper extends Publication {
}
Then we have an interface representing a publishing house with two concrete implementations, one publishes magazine and the other newspapers
public interface Publisher {
public <T extends Publication >void publish(T publication);
}
Here are the two implementations
//DOES NOT COMPILE
public class MagazinePublisher implements Publisher{
#Override
public void publish(Magazine publication) {
//do something with the magazine, its already the type we need without casting
}
}
//COMPILES but a cast is required to get the type I want
public class NewsPaperPublisher implements Publisher{
#Override
public void publish(Publication publication) {
// Now I need to cast
Newspaper newspaper = (Newspaper)publication;
//Do some stuff here
}
}
The example maybe a bit contrived... I understand why the MagazinePublisher class doesn't compile: I'm trying to implement the method with a more specific class than defined by the contract of the publish method in the interface. So how do I user generics to avoid the cast in the NewsPaperPublisher class's publish() method?
You want to make the interface generic.
public interface Publisher <T extends Publication> {
void publish(T publication);
}
Then, instead of NewspaperPublisher and MagazinePublisher, you can just write Publisher<Newspaper> and Publisher<Magazine>.
Or if you want to provide different implementations depending on the type, you can write things like
public class NewspaperPublisher implements Publisher<Newspaper> {
#Override
public void publish(Newspaper publication) {
// do some stuff
}
}
I would like to decorate a set of classes that derive from a common class (TextView). The classes exist in a library, so I cannot simply modify the base or insert into their inheritance hierarchy.
class A {
}
class B extends A {
}
class C extends A {
}
class D extends B {
void decoration(){}
}
In the example above, class D is the decorating class. The decorating functionality is common to each of my decorating classes.
My question is, is it possible to template the base class in Java? Something like:
class D<T> extends <T ? extends A> {}
So your question is about adding a method dynamically to existing classes? Something similar to categories in Objective-C. This is not simple to be done in Java since once a class is loaded through the ClassLoader you can't add anything dynamically to it.
The easiest thing that comes into my mind is to provide a custom mapping that will be by any chance external to the existing classes. Something like:
interface Method<T extends A> {
public void invoke(T ref);
}
class MethodForA implements Method<A> {
public void invoke(A ref) { .. }
}
class MethodMapper {
Map<Class<?>, Method<? extends A>> mapping;
MethodMapper() {
mapping = new HashMap<Class<?>, Method<? extends A>>();
mapping.put(A.class, new MethodForA());
}
void invoke(A object) {
Method<? extends A> method = mapping.get(object.getClass());
if (method != null) {
method.invoke(object);
}
}
I just wrote this boilerplate code right now so everything won't be surely correct but the way it would work is this one. I guess you will need to do some runtime type checks to avoid blindly casting things.
If instead you were wondering if this is legal:
class A {
}
class B<T> extends A {
}
class C<T, U> extends B<T> {
}
Yes, it is. You can make a child class generic by introducing a type parameter.