I've been wondering about the getThis() trick, and the alternative of the unsafe cast from a self-bounded type to its type parameter.
public abstract class SelfBound<T extends SelfBound<T>> {
protected abstract T getThis();
public void doSomething(T instance) { ... }
public final void doSomethingWithThis() { doSomething(getThis()); }
public final void doSomethingWithThisUnsafe() { doSomething((T) this); }
}
Is it possible to subclass SelfBound such that doSomethingWithThisUnsafe() throws a ClassCastException? (Is it possible to do this without subclassing SelfBound?)
Surely it's possible to have ClassCastException with subclassing. Here's a simple example:
public abstract class SelfBound<T extends SelfBound<T>> {
protected abstract T getThis();
public void doSomething(T instance) { }
public final void doSomethingWithThis() { doSomething(getThis()); }
public final void doSomethingWithThisUnsafe() { doSomething((T) this); }
public static class A extends SelfBound<A> {
#Override
protected A getThis() {
return this;
}
}
public static class B extends SelfBound<A> {
#Override
public void doSomething(A instance) {
super.doSomething(instance);
}
#Override
protected A getThis() {
return null;
}
}
public static void main(String[] args) {
new B().doSomethingWithThisUnsafe();
}
}
Output:
Exception in thread "main" java.lang.ClassCastException: SelfBound$B cannot be cast to SelfBound$A
at SelfBound$B.doSomething(SelfBound.java:1)
at SelfBound.doSomethingWithThisUnsafe(SelfBound.java:6)
at SelfBound.main(SelfBound.java:28)
It's not so clear what do you mean by "without subclassing SelfBound". As SelfBound is an abstract class, you cannot call its methods without subclassing it, thus you cannot have any exception when calling its methods.
Related
I have a method that returns a class type, and it is working right.
The problem is... I am getting some compilation warnings indicating unchecked conversion.
Below is the warning message I got:
Warning: java: getAjaxEventPayloadClass() in <anonymous com.iyotbihagay.wicket.panel.requestpage.resultlist.ResultList2$7> implements <P>getAjaxEventPayloadClass() in com.iyotbihagay.wicket.panel.paging.Paging.Support
return type requires unchecked conversion from java.lang.Class<com.iyotbihagay.wicket.support.RefreshSearchResultEventPayload> to java.lang.Class<P>
even if I use #SuppressWarnings("unchecked") I still cannot get rid of the compilation warning.
Below are some of the codes pointing to the warning:
ResultList2.java
public class ResultList2 {
...
private Component createPaging() {
return new Paging("paging", getRequestPageContext(), new Paging.Support() {
#Override
public void switchPage(AjaxRequestTarget target, int targetPageNum) {
getRequestPageContext().switchPage(target, targetPageNum);
}
#Override
public int getTotalNum() {
return getSearchResult().getTotalNum();
}
#Override
public int getPageSize() {
return getSearchResult().getPageSize();
}
#Override
public int getLastPageNum() {
return getSearchResult().getLastPageNum();
}
#Override
public int getCurrentPageNum() {
return getSearchResult().getCurrentPageNum();
}
#SuppressWarnings("unchecked")
#Override
public Class<RefreshSearchResultEventPayload> getAjaxEventPayloadClass() {
return RefreshSearchResultEventPayload.class;
}
#Override
public void decorateAjaxAttributes(AjaxRequestAttributes attributes, String pageNumMarkupId) {
decorateAjaxRefreshSearchResult(attributes, pageNumMarkupId);
}
});
}
...
}
Support.java
public static interface Support extends Serializable {
...
<P extends AjaxEventPayload> Class<P> getAjaxEventPayloadClass();
...
}
Paging.java
public class Paging {
...
private Support m_support;
...
#Override
public void onEvent(IEvent<?> event) {
super.onEvent(event);
WicketUtil.onEvent(event, m_support.getAjaxEventPayloadClass(), new AjaxEventHandler<AjaxEventPayload>() {
#Override
public void onEvent(IEvent<?> event, AjaxRequestTarget target, AjaxEventPayload paymentLoad) {
m_firstPageNumModel.detach();
m_previousPageNumModel.detach();
m_nextPageNumModel.detach();
m_lastPageNumModel.detach();
target.add(m_container);
}
});
}
...
}
WicketUtil.java
public class WicketUtil {
...
public static <P extends AjaxEventPayload> void onEvent(IEvent<?> event, Class<P> targetPayload, AjaxEventHandler<P> handler) {
if (event.getPayload() != null) {
if (targetPayload.isAssignableFrom(event.getPayload().getClass())) {
P p = (AjaxEventPayload)event.getPayload();
handler.onEvent(event, p.getTarget(), p);
}
}
}
...
}
m_support.getAjaxEventPayloadClass() is called/passed on WicketUtil.onEvent()... specifically on the second parameter.
RefreshSearchResultEventPayload is just one of the classes that extends AjaxEventPayload and there are other classes that extends to AjaxEventPayloadand are passed to WicketUtil.onEvent().
This should rather be:
public static interface Support extends Serializable {
...
Class<? extends AjaxEventPayload> getAjaxEventPayloadClass();
...
}
and
public class ResultList2 {
...
#Override
public Class<RefreshSearchResultEventPayload> getAjaxEventPayloadClass() {
return RefreshSearchResultEventPayload.class;
}
...
}
The reason is that <P extends AjaxEventPayload> means that the method can return a class of arbitrary payload type (as requested by the caller), e.g.:
support.<AjaxEventPayload>getAjaxEventPayloadClass()
instead of returning only the one payload type that is specific to the implementing class (e.g. RefreshSearchResultEventPayload).
I have the following situation:
abstract class Base {
int data = 0;
void baseMethod() {
System.out.println("baseMethod:" + data);
}
}
class DerivedA extends Base {
void DerivedBMethodA() {
}
void usefulMethod(Something something) {
something.doSomething(this);
}
interface Something {
void doSomething(DerivedA deriv);
}
}
class DerivedB extends Base {
void DerivedMethodB() {
}
}
public class Temp {
public static void main() {
DerivedA a = new DerivedA();
a.usefulMethod(new DerivedA.Something() {
#Override
public void doSomething(DerivedA deriv) {
deriv.DerivedBMethodA();
}
});
}
}
I want to push usefulMethod and Something upto the Base class so that DerivedB can leverage it. And I want implementations of Something.doSomething to be able to use a derived type, so that it can access derived functionality.
How do I do that?
Attempts
I've tried the following:
abstract class Base {
int data = 0;
void baseMethod() {
System.out.println("baseMethod:" + data);
}
void usefulMethod(Something something) {
something.doSomething(this);
}
interface Something {
void doSomething(Base deriv);
}
}
class DerivedA extends Base {
void DerivedBMethodA() {
}
}
class DerivedB extends Base {
void DerivedMethodB() {
}
}
public class Temp {
public static void main() {
DerivedA a = new DerivedA();
a.usefulMethod(new Base.Something() {
#Override
public void doSomething(DerivedA deriv) {
deriv.DerivedBMethodA();
}
});
}
}
but that fails as my anonymous Something doesn't implement doSomething(Base). So trying to use generics:
I tried:
interface Something {
void doSomething(<? extends Base> deriv);
}
but that won't compile due to: "Wildcards may be used only as reference parameters"
I tried:
interface Something {
<T extends Base> void doSomething(T deriv);
}
but that requires me to implement the interface as so:
a.usefulMethod(new Base.Something() {
#Override
public <T extends Base> void doSomething(T deriv) {
}
});
which obviously doesn't allow me access to the derived type?
There are ways I can make it "work" but they're undesirable:
This:
interface Something {
void doSomething(Base deriv);
}
a.usefulMethod(new Base.Something() {
#Override
public void doSomething(Base deriv) {
DerivedA a1 = (DerivedA) deriv;
a1.DerivedBMethodA();
}
});
But that requires me to cast in each implementation, which seems wasteful.
And this:
package com.miurasample.ui.info;
abstract class Base {
int data = 0;
void baseMethod() {
System.out.println("baseMethod:" + data);
}
void usefulMethod(Something something) {
something.doSomething(this);
}
interface Something<T extends Base> {
void doSomething(T deriv);
}
}
public class Temp {
public static void main() {
DerivedA a = new DerivedA();
a.usefulMethod(new Base.Something<DerivedA>() {
#Override
public void doSomething(DerivedA deriv) {
}
});
}
}
but that results in a warning/IDE highlight in usefulMethod of:
"Unchecked call to doSomething(T) as a member of raw type Base.Something"
What's the tersest and "cleanest" way to do this? Is that I'm doing even sane?
It is difficult to say if your design is wrong or not. We dont have full scope of your requirements to assert that, but here is clean non cast approach to what you are trying to do. It does require extra method in your derived classes:
public static void main(String... args) {
DerivedA a = new DerivedA();
a.usefulMethod( new Base.Something<DerivedA>() {
#Override
public void doSomething(DerivedA deriv) {
deriv.DerivedBMethodA();
}
} );
}
public abstract static class Base< T extends Base<T> > {
int data = 0;
protected abstract T getThis();
void baseMethod() {
System.out.println("baseMethod:" + data);
}
void usefulMethod(Something<T> something) {
something.doSomething( getThis() );
}
interface Something< T extends Base<T> > {
void doSomething(T deriv);
}
}
public static class DerivedA extends Base<DerivedA> {
protected DerivedA getThis(){
return this;
}
void DerivedBMethodA() {}
}
public static class DerivedB extends Base<DerivedB> {
protected DerivedB getThis(){
return this;
}
void DerivedMethodB() {}
}
Please help resolve an issue regarding generics. I tried many ways but it's still not working.
Problem is:
public static void main(String[] args) {
Utils.execute(new TestAction(), new TestCallBack());
}
Compiler show error:
The method execute(Action<?>, CallBack<?,Action<?>>) in the type Utils is not applicable for the arguments (ImplementClass.TestAction, ImplementClass.TestCallBack)
My classes is:
Action class:
public abstract class Action<R> {
public R getResult() {
return null;
}
}
TestAction class is:
class TestAction extends Action<String> {
#Override
public String getResult() {
return super.getResult();
}
}
Callback class is:
public interface CallBack<R, A extends Action<R>> {
public void onCall(A action);}
TestCallback class is:
class TestCallBack implements CallBack<String, TestAction> {
#Override
public void onCall(TestAction action) {
}
}
And Utils class is:
public class Utils {
public static void execute(Action<?> action, CallBack<?, Action<?>> callback) {
}
}
Thanks a lot.
The second parameter of the execute method is CallBack<?, Action<?>>, and Action there means the Action class itself, subclass of it is not allowed. What you need there is - ? extends Action<?>, which means either Action or some subclass of it.
Try changing the method signature -
public static void execute(Action<?> action, CallBack<?, ? extends Action<?>> callback) {
Note:
Generics are not co-variant. Take for example a method as follows -
static void method(List<Object> l) {}
And an invocation as follows is not allowed -
method(new ArrayList<String>());
You need to change two things,
TestCallBack should be like this -
public static class TestCallBack implements CallBack<String, Action<String>> {
#Override
public void onCall(Action<String> action) {
}
}
and, Utils should be like this -
public static class Utils {
// You need to ensure the same type, not just try and accept anything.
public static <T> void execute(Action<T> action, CallBack<?, Action<T>> callback) {
}
}
or using inner classes of a class called Question -
public abstract class Action<R> {
public R getResult() {
return null;
}
}
public class TestAction extends Action<String> {
#Override
public String getResult() {
return super.getResult();
}
}
public interface CallBack<R, A extends Action<R>> {
public void onCall(A action);
}
public class TestCallBack implements CallBack<String, TestAction> {
#Override
public void onCall(TestAction action) {
}
}
public class Utils {
public void execute(Action<?> action, CallBack<?, ? extends Action<?>> callback) {
}
}
public static void main(String[] args) {
Question question = new Question();
question.new Utils().execute(question.new TestAction(), question.new TestCallBack());
}
I have an abstract class called "Operation"
and this class has an abstract method called "Prepare".
public abstract class Operation {
public abstract void prepare() throws Exception;
public abstract void run() throws Exception;
// other stuff here that's not abstract
public void printHelloWorld() {
System.out.println("Hello World!");
}
}
The only issue is that some things that are "Operation" (
some classes that extends Operation ) need arguments to prepare ( some
need ints, some need String, some need more complex data types..so it's not always an int )
public class Teleportation extends Operation {
#Override
public void prepare(int capacityRequired ) throws Exception {
// do stuff
}
#Override
public void run() throws Exception {
}
}
What OOP pattern do I use to achieve this
and how do I set up this code ?
EDIT :
Ideally, I want to prepare and run operations like this :
for (Operation operation : operations ) {
operation.prepare();
operation.run();
}
Assuming I use this solution :
public class Teleportation extends Operation {
private int cReq;
public void setCapacityRequired(int cReq) {
this.cReq = cReq;
}
#Override
public void prepare() throws Exception {
// I can do the preparation stuff
// since I have access to cReq here
}
#Override
public void run() throws Exception {
}
}
Then - I wonder if it's possible to avoid this :
for (Operation operation : operations ) {
if (operation.getClass().isInstanceOf(Teleporation.class)) {
((Teleporation)operation).setCapacityRequired( 5 );
}
operation.prepare();
operation.run();
}
I would recommend having an additional constructor where you can add the necessary data that the implementation requires and store it in fields for the class implementation.
For your example:
public class Teleportation extends Operation {
private final int capacityRequired;
public Teleportation(int capacityRequired) {
this.capacityRequired = capacityRequired;
}
public void prepare() throws Exception {
// do stuff using the capacityRequired field...
}
}
This approach applies for more complex parameters as well.
The very first thing to do here is to override the abstract class operation and overload with your capacity.
public class Teleportation extends Operation {
public void prepare() throws Exception {
prepare(0);
}
public void prepare(int capacityRequired) throws Exception {
//do stuff
}
}
And remember the KISS and YAGNI statements, there is no need to use design patterns anywhere in your code, just where they makes things simpler.
You either need to expand the abstract class to include two method signatures or change the signature to take a varargs int parameter:
public abstract class Operation {
public abstract void prepare(int... args) throws Exception;
}
You can use generic class for your operation class:
public abstract class Operation<T>
{
private T operationModel;
public Operation(T operationModel)
{
super();
this.operationModel = operationModel;
}
public abstract void prepare() throws Exception;
public abstract void run() throws Exception;
public T getOperationModel()
{
return operationModel;
}
}
Then for concrete classes, extend it with proper parameter-type (You can have a specific class for each operation):
public class TeleOperation extends Operation<TeleOperationModel>
{
public TeleOperation(TeleOperationModel operationModel)
{
super(operationModel);
}
#Override
public void prepare() throws Exception
{
TeleOperationModel teleOperationModel = getOperationModel();
//...
}
#Override
public void run() throws Exception
{
}
}
public class TeleOperationModel
{
private int capacity;
....
}
and:
public class MicroOperation extends Operation<MicroOperationModel>
{
public MicroOperation(MicroOperationModel operationModel)
{
super(operationModel);
}
#Override
public void prepare() throws Exception
{
MicroOperationModel microOperationModel = getOperationModel();
//...
}
#Override
public void run() throws Exception
{
}
}
public class MicroOperationModel
{
private int x;
private int y;
private int z;
....
}
I am not familiar with "Generics". Is it a correct use of "<T extends SuperClass>" ? And do you agree that the codes after using generics are better?
Before using Generics
=================================================
public abstract class SuperSample {
public void getSomething(boolean isProcessA) {
doProcessX();
if(isProcessA){
doProcessY(new SubASample());
}else{
doProcessY(new SubBSample());
}
}
protected abstract void doProcessX();
protected void doProcessY(SubASample subASample) {
// Nothing to do
}
protected void doProcessY(SubBSample subBSample) {
// Nothing to do
}
}
public class SubASample extends SuperSample {
#Override
protected void doProcessX() {
System.out.println("doProcessX in SubASample");
}
#Override
protected void doProcessY(SubASample subASample) {
System.out.println("doProcessY in SubASample");
}
}
public class Sample {
public static void main(String[] args) {
SubASample subASample = new SubASample();
subASample.getSomething(true);
}
}
After using Generics
=================================================
public abstract class SuperSample {
public void getSomething(boolean isProcessA) {
doProcessX();
if(isProcessA){
doProcessY(new SubASample());
}else{
doProcessY(new SubBSample());
}
}
protected abstract void doProcessX();
protected abstract <T extends SuperSample> void doProcessY(T subSample);
}
public class SubASample extends SuperSample {
#Override
protected void doProcessX() {
System.out.println("doProcessX in SubASample");
}
#Override
protected <T extends SuperSample> void doProcessY(T subSample) {
System.out.println("doProcessY in SubASample");
}
}
public class Sample {
public static void main(String[] args) {
SubASample subASample = new SubASample();
subASample.getSomething(true);
}
}
If you want to do what I think you want to do, I don't think that this is the right way (*). If you want that every subclass needs to implement a method that processes it's own type, then you can use the CRTP trick:
abstract class Super<S extends Super<S>> {
abstract void process(S s);
}
class SubA extends Super<SubA> {
void process(SubA s){ /* do something */ }
}
class SubB extends Super<SubB> {
void process(SubB s){ /* do something */ }
}
Note that this pattern enforces the generic signature of the subclasses, e.g. class SubA extends Super<SubB> wouldn't compile.
Java itself uses that trick in java.lang.Enum, by the way.
(*)If this is not the behavior you want to enforce, please clarify.
it's correct to use . It means that you restrict type T to be subclass of SuperSample. And for second answer, yes I think code with generecis is better because it keeps you from wrong casting of classes for example with containers (List ...). But in fact generics in Java are only syntax suger and so they are erased during runtime.