Java: How to write method to accept child without casting to parent? - java

Not sure how to title this...
So I've got three child classes of Event: WeightEvent, TimedEvent, RepEvent. Through whatever means, I get an object of one of the children. Now I want to send that child event to a method in another object so it can pull the data from it with the getSavedEvents() method. The method only exists in the children since pulling the data is specific to the type of event.
I started with
public void setEvent(Event e) {
but that cast my child object to an Event (parent) object.
Is there any way around this short of writing three different methods. One each for the children?
public void setEvent(WeightEvent e) {
public void setEvent(TimedEvent e) {
public void setEvent(RepEvent e) {
Thanks for any advice.
-John

Even though the reference is cast, it doesn't change the type of the actual object. When you pass the reference on, it will still be a reference to an instance of the child object. Normally this would be enough, with appropriate abstract methods in the parent type if necessary.
However, if the methods you want are specific to the types of the children and you can't come up with an appropriate abstraction which all of them can implement generically, then either you've got to use instanceof within your setEvent code or you do have to overload your method... because you're going to have to call different bits of code depending on the exact type of the event.
This is all a bit vague because we can't see any of your code except a couple of method signatures. If you could give us more details about what you're trying to do, particularly in terms of what setEvent needs to achieve and what the different methods in the child classes are, we may be able to help more.

Instead of switching on the type you should call a method on the event that's defined differently for each type of event type. This is called the Template method pattern. (It has nothing to do with C++ templates, BTW)
Using this pattern, your EventTable class becomes something like this:
public class EventTable {
public void setEvent(Event e) {
int x = 0;
columns = e.getFields();
Event[] savedEvents = e.getSavedEvents();
for(Event ev : savedEvents) {
tempdata[x] = ev.getTempData();
x++;
}
}
}
Note that the entire switch has been replaced with a single call to getTempData(). This method is then abstract in Event, just like getSavedEvents:
public abstract class Event {
public Date getDate() { return(_date); }
public abstract Event[] getSavedEvents();
public abstract int[] getTempData();
public int[] getFormattedDate() {
...
}
Then you define the getTempData() method in each subclass. For example:
public class WeightEvent extends Event {
public int getWeight() { return(_weight); }
public int getReps() { return(_reps); }
public int[] getTempData() {
return new int[]{
getFormattedDate()[0],
getWeight(),
getReps()
};
}
}
public class TimedEvent extends Event {
public String getTimeInHMS() { return(_timeString); }
public int[] getTempData() {
return new int[]{
getFormattedDate()[0],
getTimeInHMS()
};
}
}
public class RepEvent extends Event {
public int getReps() { return(_reps); }
public int[] getTempData() {
return new int[]{
getFormattedDate()[0],
getReps()
};
}
}

You could use generics to do this.
Define the Event class as follows:
public abstract class Event<T extends Event> {
public abstract void setEvent(T e);
}
This defines a class that expects to be created with any type that extends Event.
Then in your child classes you implement something like this using the child class as the generic type:
class WeightEvent extends Event<WeightEvent>
{
#Override
public void setEvent(WeightEvent e) {
...
}
}

I think your probem is calling getSavedEvents() when having an Event variable.
If so, add an abstract getSavedEvents() method to Event, which must also be declared abstract :
public abstract class Event {
public abstract Events getSavedEvents();
...
}
since Eventis abstract you can not create an instance of it; it must be subclassed to be used. If that is a problem, throw an Exception or do anything reasonable for your application (nothing at all, just return null) in Event.getSavedEvents():
public class Event {
public Events getSavedEvents() {
throw new UnsupportedOperationException("must be called in a child class");
// OR return null;
...
}
now you can call the getSavedEvents() method in your other object:
public class OtherObject {
private Event event;
public void setEvent(Event e) {
event = e;
...
Events events = event.getSavesEvents();
the method implemented by the real class of e will be used, e.g. if e is a TimedEvent, the method in that class will be called.

You could abstract the problem out behind an interface
interface IEvent
{
abstract public void doSomething();
}
Then have all your event classes implement it, e.g.
class WeightedEvent implements IEvent
{
public void doSomething()
{
// do something
}
}
Then you only need a single method and don't need to do any type checking
public void setEvent(IEvent e)
{
e.doSomething();
}
HTH

May be you can use a Visitor pattern.

Using abstract helped with the getSavedEvents() method, since all of the children implement that method.
Here's the code for setEvent():
public class EventTable {
public void setEvent(Event e) {
int x = 0;
int type = e.getEventType();
columns = e.getFields();
Event[] savedEvents = e.getSavedEvents();
for(Event ev : savedEvents) {
tempdata[x][0] = ev.getFormattedDate()[0];
switch(type) {
case EVENTTYPE.WEIGHT:
tempdata[x][1] = ev.getWeight();
tempdata[x][2] = ev.getReps();
break;
case EVENTTYPE.TIMED:
tempdata[x][1] = ev.getTimeInHMS();
break;
case EVENTTYPE.REP:
tempdata[x][1] = ev.getReps();
break;
}
x++;
}
}
}
This code works after I added "abstract" to the Event class and defined an abstract method called getSavedEvents().
The next problem is the getWeight(), getReps() and getTimeInHMS() methods. They are specific to the type of child event and again don't exist in the parent Event class. If I make them abstract in Event, now I have to define them in each child, even though getReps() has no context for a TimedEvent.
public class Event {
public Date getDate() { return(_date); }
}
public class WeightEvent extends Event {
public int getWeight() { return(_weight); }
public int getReps() { return(_reps); }
}
public class TimedEvent extends Event {
public String getTimeInHMS() { return(_timeString); }
}
public class RepEvent extends Event {
public int getReps() { return(_reps); }
}
Abbreviated code, obviously. WeightEvents have a date, weight and reps associated with them. TimedEvents have a date and length of time associated with them. RepEvents have a date and number of reps associated to them. The date methods are all in the parent since they are common across events.
If I don't make getWeight(), getReps() abstract and only declare them in the child where they are relevant, here's the error I get from EventTable in the above copied setEvent() method:
EventTable.java:124: cannot find symbol
symbol : method getWeight()
location: class Event
tempdata[x][1] = ev.getWeight();
-John

You could cast the Event e object to the child classes -- I think the instanceof operator in Java will help you.

Related

How do I access a superclass method in java if it has already been overridden by a subclass? [duplicate]

I read this question and thought that would easily be solved (not that it isn't solvable without) if one could write:
#Override
public String toString() {
return super.super.toString();
}
I'm not sure if it is useful in many cases, but I wonder why it isn't and if something like this exists in other languages.
What do you guys think?
EDIT:
To clarify: yes I know, that's impossible in Java and I don't really miss it. This is nothing I expected to work and was surprised getting a compiler error. I just had the idea and like to discuss it.
It violates encapsulation. You shouldn't be able to bypass the parent class's behaviour. It makes sense to sometimes be able to bypass your own class's behaviour (particularly from within the same method) but not your parent's. For example, suppose we have a base "collection of items", a subclass representing "a collection of red items" and a subclass of that representing "a collection of big red items". It makes sense to have:
public class Items
{
public void add(Item item) { ... }
}
public class RedItems extends Items
{
#Override
public void add(Item item)
{
if (!item.isRed())
{
throw new NotRedItemException();
}
super.add(item);
}
}
public class BigRedItems extends RedItems
{
#Override
public void add(Item item)
{
if (!item.isBig())
{
throw new NotBigItemException();
}
super.add(item);
}
}
That's fine - RedItems can always be confident that the items it contains are all red. Now suppose we were able to call super.super.add():
public class NaughtyItems extends RedItems
{
#Override
public void add(Item item)
{
// I don't care if it's red or not. Take that, RedItems!
super.super.add(item);
}
}
Now we could add whatever we like, and the invariant in RedItems is broken.
Does that make sense?
I think Jon Skeet has the correct answer. I'd just like to add that you can access shadowed variables from superclasses of superclasses by casting this:
interface I { int x = 0; }
class T1 implements I { int x = 1; }
class T2 extends T1 { int x = 2; }
class T3 extends T2 {
int x = 3;
void test() {
System.out.println("x=\t\t" + x);
System.out.println("super.x=\t\t" + super.x);
System.out.println("((T2)this).x=\t" + ((T2)this).x);
System.out.println("((T1)this).x=\t" + ((T1)this).x);
System.out.println("((I)this).x=\t" + ((I)this).x);
}
}
class Test {
public static void main(String[] args) {
new T3().test();
}
}
which produces the output:
x= 3
super.x= 2
((T2)this).x= 2
((T1)this).x= 1
((I)this).x= 0
(example from the JLS)
However, this doesn't work for method calls because method calls are determined based on the runtime type of the object.
I think the following code allow to use super.super...super.method() in most case.
(even if it's uggly to do that)
In short
create temporary instance of ancestor type
copy values of fields from original object to temporary one
invoke target method on temporary object
copy modified values back to original object
Usage :
public class A {
public void doThat() { ... }
}
public class B extends A {
public void doThat() { /* don't call super.doThat() */ }
}
public class C extends B {
public void doThat() {
Magic.exec(A.class, this, "doThat");
}
}
public class Magic {
public static <Type, ChieldType extends Type> void exec(Class<Type> oneSuperType, ChieldType instance,
String methodOfParentToExec) {
try {
Type type = oneSuperType.newInstance();
shareVars(oneSuperType, instance, type);
oneSuperType.getMethod(methodOfParentToExec).invoke(type);
shareVars(oneSuperType, type, instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static <Type, SourceType extends Type, TargetType extends Type> void shareVars(Class<Type> clazz,
SourceType source, TargetType target) throws IllegalArgumentException, IllegalAccessException {
Class<?> loop = clazz;
do {
for (Field f : loop.getDeclaredFields()) {
if (!f.isAccessible()) {
f.setAccessible(true);
}
f.set(target, f.get(source));
}
loop = loop.getSuperclass();
} while (loop != Object.class);
}
}
I don't have enough reputation to comment so I will add this to the other answers.
Jon Skeet answers excellently, with a beautiful example. Matt B has a point: not all superclasses have supers. Your code would break if you called a super of a super that had no super.
Object oriented programming (which Java is) is all about objects, not functions. If you want task oriented programming, choose C++ or something else. If your object doesn't fit in it's super class, then you need to add it to the "grandparent class", create a new class, or find another super it does fit into.
Personally, I have found this limitation to be one of Java's greatest strengths. Code is somewhat rigid compared to other languages I've used, but I always know what to expect. This helps with the "simple and familiar" goal of Java. In my mind, calling super.super is not simple or familiar. Perhaps the developers felt the same?
There's some good reasons to do this. You might have a subclass which has a method which is implemented incorrectly, but the parent method is implemented correctly. Because it belongs to a third party library, you might be unable/unwilling to change the source. In this case, you want to create a subclass but override one method to call the super.super method.
As shown by some other posters, it is possible to do this through reflection, but it should be possible to do something like
(SuperSuperClass this).theMethod();
I'm dealing with this problem right now - the quick fix is to copy and paste the superclass method into the subsubclass method :)
In addition to the very good points that others have made, I think there's another reason: what if the superclass does not have a superclass?
Since every class naturally extends (at least) Object, super.whatever() will always refer to a method in the superclass. But what if your class only extends Object - what would super.super refer to then? How should that behavior be handled - a compiler error, a NullPointer, etc?
I think the primary reason why this is not allowed is that it violates encapsulation, but this might be a small reason too.
I think if you overwrite a method and want to all the super-class version of it (like, say for equals), then you virtually always want to call the direct superclass version first, which one will call its superclass version in turn if it wants.
I think it only makes rarely sense (if at all. i can't think of a case where it does) to call some arbitrary superclass' version of a method. I don't know if that is possible at all in Java. It can be done in C++:
this->ReallyTheBase::foo();
At a guess, because it's not used that often. The only reason I could see using it is if your direct parent has overridden some functionality and you're trying to restore it back to the original.
Which seems to me to be against OO principles, since the class's direct parent should be more closely related to your class than the grandparent is.
Calling of super.super.method() make sense when you can't change code of base class. This often happens when you are extending an existing library.
Ask yourself first, why are you extending that class? If answer is "because I can't change it" then you can create exact package and class in your application, and rewrite naughty method or create delegate:
package com.company.application;
public class OneYouWantExtend extends OneThatContainsDesiredMethod {
// one way is to rewrite method() to call super.method() only or
// to doStuff() and then call super.method()
public void method() {
if (isDoStuff()) {
// do stuff
}
super.method();
}
protected abstract boolean isDoStuff();
// second way is to define methodDelegate() that will call hidden super.method()
public void methodDelegate() {
super.method();
}
...
}
public class OneThatContainsDesiredMethod {
public void method() {...}
...
}
For instance, you can create org.springframework.test.context.junit4.SpringJUnit4ClassRunner class in your application so this class should be loaded before the real one from jar. Then rewrite methods or constructors.
Attention: This is absolute hack, and it is highly NOT recommended to use but it's WORKING! Using of this approach is dangerous because of possible issues with class loaders. Also this may cause issues each time you will update library that contains overwritten class.
#Jon Skeet Nice explanation.
IMO if some one wants to call super.super method then one must be want to ignore the behavior of immediate parent, but want to access the grand parent behavior.
This can be achieved through instance Of. As below code
public class A {
protected void printClass() {
System.out.println("In A Class");
}
}
public class B extends A {
#Override
protected void printClass() {
if (!(this instanceof C)) {
System.out.println("In B Class");
}
super.printClass();
}
}
public class C extends B {
#Override
protected void printClass() {
System.out.println("In C Class");
super.printClass();
}
}
Here is driver class,
public class Driver {
public static void main(String[] args) {
C c = new C();
c.printClass();
}
}
Output of this will be
In C Class
In A Class
Class B printClass behavior will be ignored in this case.
I am not sure about is this a ideal or good practice to achieve super.super, but still it is working.
Look at this Github project, especially the objectHandle variable. This project shows how to actually and accurately call the grandparent method on a grandchild.
Just in case the link gets broken, here is the code:
import lombok.val;
import org.junit.Assert;
import org.junit.Test;
import java.lang.invoke.*;
/*
Your scientists were so preoccupied with whether or not they could, they didn’t stop to think if they should.
Please don't actually do this... :P
*/
public class ImplLookupTest {
private MethodHandles.Lookup getImplLookup() throws NoSuchFieldException, IllegalAccessException {
val field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
field.setAccessible(true);
return (MethodHandles.Lookup) field.get(null);
}
#Test
public void test() throws Throwable {
val lookup = getImplLookup();
val baseHandle = lookup.findSpecial(Base.class, "toString",
MethodType.methodType(String.class),
Sub.class);
val objectHandle = lookup.findSpecial(Object.class, "toString",
MethodType.methodType(String.class),
// Must use Base.class here for this reference to call Object's toString
Base.class);
val sub = new Sub();
Assert.assertEquals("Sub", sub.toString());
Assert.assertEquals("Base", baseHandle.invoke(sub));
Assert.assertEquals(toString(sub), objectHandle.invoke(sub));
}
private static String toString(Object o) {
return o.getClass().getName() + "#" + Integer.toHexString(o.hashCode());
}
public class Sub extends Base {
#Override
public String toString() {
return "Sub";
}
}
public class Base {
#Override
public String toString() {
return "Base";
}
}
}
Happy Coding!!!!
I would put the super.super method body in another method, if possible
class SuperSuperClass {
public String toString() {
return DescribeMe();
}
protected String DescribeMe() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return "I am super";
}
}
class ChildClass extends SuperClass {
public String toString() {
return DescribeMe();
}
}
Or if you cannot change the super-super class, you can try this:
class SuperSuperClass {
public String toString() {
return "I am super super";
}
}
class SuperClass extends SuperSuperClass {
public String toString() {
return DescribeMe(super.toString());
}
protected String DescribeMe(string fromSuper) {
return "I am super";
}
}
class ChildClass extends SuperClass {
protected String DescribeMe(string fromSuper) {
return fromSuper;
}
}
In both cases, the
new ChildClass().toString();
results to "I am super super"
It would seem to be possible to at least get the class of the superclass's superclass, though not necessarily the instance of it, using reflection; if this might be useful, please consider the Javadoc at http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass()
public class A {
#Override
public String toString() {
return "A";
}
}
public class B extends A {
#Override
public String toString() {
return "B";
}
}
public class C extends B {
#Override
public String toString() {
return "C";
}
}
public class D extends C {
#Override
public String toString() {
String result = "";
try {
result = this.getClass().getSuperclass().getSuperclass().getSuperclass().newInstance().toString();
} catch (InstantiationException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
Logger.getLogger(D.class.getName()).log(Level.SEVERE, null, ex);
}
return result;
}
}
public class Main {
public static void main(String... args) {
D d = new D();
System.out.println(d);
}
}
run:
A
BUILD SUCCESSFUL (total time: 0 seconds)
I have had situations like these when the architecture is to build common functionality in a common CustomBaseClass which implements on behalf of several derived classes.
However, we need to circumvent common logic for specific method for a specific derived class. In such cases, we must use a super.super.methodX implementation.
We achieve this by introducing a boolean member in the CustomBaseClass, which can be used to selectively defer custom implementation and yield to default framework implementation where desirable.
...
FrameworkBaseClass (....) extends...
{
methodA(...){...}
methodB(...){...}
...
methodX(...)
...
methodN(...){...}
}
/* CustomBaseClass overrides default framework functionality for benefit of several derived classes.*/
CustomBaseClass(...) extends FrameworkBaseClass
{
private boolean skipMethodX=false;
/* implement accessors isSkipMethodX() and setSkipMethodX(boolean)*/
methodA(...){...}
methodB(...){...}
...
methodN(...){...}
methodX(...){
if (isSkipMethodX()) {
setSKipMethodX(false);
super.methodX(...);
return;
}
... //common method logic
}
}
DerivedClass1(...) extends CustomBaseClass
DerivedClass2(...) extends CustomBaseClass
...
DerivedClassN(...) extends CustomBaseClass...
DerivedClassX(...) extends CustomBaseClass...
{
methodX(...){
super.setSKipMethodX(true);
super.methodX(...);
}
}
However, with good architecture principles followed in framework as well as app, we could avoid such situations easily, by using hasA approach, instead of isA approach. But at all times it is not very practical to expect well designed architecture in place, and hence the need to get away from solid design principles and introduce hacks like this.
Just my 2 cents...
IMO, it's a clean way to achieve super.super.sayYourName() behavior in Java.
public class GrandMa {
public void sayYourName(){
System.out.println("Grandma Fedora");
}
}
public class Mama extends GrandMa {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName();
}else {
System.out.println("Mama Stephanida");
}
}
}
public class Daughter extends Mama {
public void sayYourName(boolean lie){
if(lie){
super.sayYourName(lie);
}else {
System.out.println("Little girl Masha");
}
}
}
public class TestDaughter {
public static void main(String[] args){
Daughter d = new Daughter();
System.out.print("Request to lie: d.sayYourName(true) returns ");
d.sayYourName(true);
System.out.print("Request not to lie: d.sayYourName(false) returns ");
d.sayYourName(false);
}
}
Output:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
I think this is a problem that breaks the inheritance agreement.
By extending a class you obey / agree its behavior, features
Whilst when calling super.super.method(), you want to break your own obedience agreement.
You just cannot cherry pick from the super class.
However, there may happen situations when you feel the need to call super.super.method() - usually a bad design sign, in your code or in the code you inherit !
If the super and super super classes cannot be refactored (some legacy code), then opt for composition over inheritance.
Encapsulation breaking is when you #Override some methods by breaking the encapsulated code.
The methods designed not to be overridden are marked
final.
In C# you can call a method of any ancestor like this:
public class A
internal virtual void foo()
...
public class B : A
public new void foo()
...
public class C : B
public new void foo() {
(this as A).foo();
}
Also you can do this in Delphi:
type
A=class
procedure foo;
...
B=class(A)
procedure foo; override;
...
C=class(B)
procedure foo; override;
...
A(objC).foo();
But in Java you can do such focus only by some gear. One possible way is:
class A {
int y=10;
void foo(Class X) throws Exception {
if(X!=A.class)
throw new Exception("Incorrect parameter of "+this.getClass().getName()+".foo("+X.getName()+")");
y++;
System.out.printf("A.foo(%s): y=%d\n",X.getName(),y);
}
void foo() throws Exception {
System.out.printf("A.foo()\n");
this.foo(this.getClass());
}
}
class B extends A {
int y=20;
#Override
void foo(Class X) throws Exception {
if(X==B.class) {
y++;
System.out.printf("B.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("B.foo(%s) calls B.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
}
class C extends B {
int y=30;
#Override
void foo(Class X) throws Exception {
if(X==C.class) {
y++;
System.out.printf("C.foo(%s): y=%d\n",X.getName(),y);
} else {
System.out.printf("C.foo(%s) calls C.super.foo(%s)\n",X.getName(),X.getName());
super.foo(X);
}
}
void DoIt() {
try {
System.out.printf("DoIt: foo():\n");
foo();
Show();
System.out.printf("DoIt: foo(B):\n");
foo(B.class);
Show();
System.out.printf("DoIt: foo(A):\n");
foo(A.class);
Show();
} catch(Exception e) {
//...
}
}
void Show() {
System.out.printf("Show: A.y=%d, B.y=%d, C.y=%d\n\n", ((A)this).y, ((B)this).y, ((C)this).y);
}
}
objC.DoIt() result output:
DoIt: foo():
A.foo()
C.foo(C): y=31
Show: A.y=10, B.y=20, C.y=31
DoIt: foo(B):
C.foo(B) calls C.super.foo(B)
B.foo(B): y=21
Show: A.y=10, B.y=21, C.y=31
DoIt: foo(A):
C.foo(A) calls C.super.foo(A)
B.foo(A) calls B.super.foo(A)
A.foo(A): y=11
Show: A.y=11, B.y=21, C.y=31
It is simply easy to do. For instance:
C subclass of B and B subclass of A. Both of three have method methodName() for example.
public abstract class A {
public void methodName() {
System.out.println("Class A");
}
}
public class B extends A {
public void methodName() {
super.methodName();
System.out.println("Class B");
}
// Will call the super methodName
public void hackSuper() {
super.methodName();
}
}
public class C extends B {
public static void main(String[] args) {
A a = new C();
a.methodName();
}
#Override
public void methodName() {
/*super.methodName();*/
hackSuper();
System.out.println("Class C");
}
}
Run class C Output will be:
Class A
Class C
Instead of output:
Class A
Class B
Class C
If you think you are going to be needing the superclass, you could reference it in a variable for that class. For example:
public class Foo
{
public int getNumber()
{
return 0;
}
}
public class SuperFoo extends Foo
{
public static Foo superClass = new Foo();
public int getNumber()
{
return 1;
}
}
public class UltraFoo extends Foo
{
public static void main(String[] args)
{
System.out.println(new UltraFoo.getNumber());
System.out.println(new SuperFoo().getNumber());
System.out.println(new SuperFoo().superClass.getNumber());
}
public int getNumber()
{
return 2;
}
}
Should print out:
2
1
0
public class SubSubClass extends SubClass {
#Override
public void print() {
super.superPrint();
}
public static void main(String[] args) {
new SubSubClass().print();
}
}
class SuperClass {
public void print() {
System.out.println("Printed in the GrandDad");
}
}
class SubClass extends SuperClass {
public void superPrint() {
super.print();
}
}
Output: Printed in the GrandDad
The keyword super is just a way to invoke the method in the superclass.
In the Java tutorial:https://docs.oracle.com/javase/tutorial/java/IandI/super.html
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super.
Don't believe that it's a reference of the super object!!! No, it's just a keyword to invoke methods in the superclass.
Here is an example:
class Animal {
public void doSth() {
System.out.println(this); // It's a Cat! Not an animal!
System.out.println("Animal do sth.");
}
}
class Cat extends Animal {
public void doSth() {
System.out.println(this);
System.out.println("Cat do sth.");
super.doSth();
}
}
When you call cat.doSth(), the method doSth() in class Animal will print this and it is a cat.

Java invoke child method from parent object

I've got next situation:
There is an abstract class
public abstract class SuperClass {
public abstract void getString();
public abstract void method2();
}
public class InheritClass1 extends SuperClass {
#Override
public void getString(){...};
#Override
public void method2(){...};
}
public class InheritClass2 extends SuperClass {
#Override
public void getString{...};
#Override
public void method2(){...};
public void customMethod(){...};
}
There is another class that has a method that accepts SuperClass object as an argument. Depending on what kind of String is returned from getString I perform different actions. My case is that I am trying to call a child method while the object is of parent class:
public class Processor {
public String method(SuperClass type) {
switch (type.getString()) {
case "1":
return "OK"
case "2":
return ((InheritClass2) type).customMethod()
}
}
I do understand that this is BAD DESIGN, could you please help me with finding the best solution for this problem. Maybe generics are suitable in this case somehow. Also the thing is that customMethod() should be a part of not all classes.
Since only some (sub)classes implements customMethod, I would suggest to create an interface that contains this method:
public interface CustomInterface {
public String customMethod();
}
Your SuperClass can then remain just as it is. Only the subclasses/child classes that have customMethod, would then extend your SuperClass as well as implement this CustomInterface. This way, the child classes that do not implement CustomMethod (does not have the method in their class, such as InheritClass1 in your example), also remain just as they are.
Only child classes that have CustomMethod, such as InheritClass2 would then need to change slightly by saying it implements this new interface:
public class InheritClass2 extends SuperClass implements CustomInteface {
// the rest stays the same
}
Then in the section where you want to do the casting, you rather do the following:
public class Processor {
public String method(SuperClass type) {
switch (type.getString()) {
case "1":
return "OK"
case "2":
String s = "";
if (type instance of CustomInterface) {
s = (CustomInterface type).customMethod();
}
return s;
}
}
}
Using the interface in this way will help that you can implement all child classes and not just one as implementing the CustomInterface, and thus, all child classes will work with using instanceof and casting to the interface to call customMethod() - you won't have to handle each child that needs this method separately.
NOTE: Your code is clearly simplified example, it is unclear if the getString() method is just returning an identifier of the child classes in order for you to know which ones you can cast and then call custom Method on... If this is the purpose of your switch and getString methods - to identify which types implement the customMethod() and to call that method, and for any child class that does not have that method to return just "OK" - then you could instead do the following:
public class SubClass1 extends SuperClass implements CustomInterface {
// other mehtods...
public String CustomMethod() { return "SomeString1"; }
}
public class SubClass2 extends SuperClass {
// other methods...
// this subclass does not have the CustomMethod()
}
public class SubClass3 extends SuperClass implements CustomInterface {
// other methods...
public String CustomMethod() { return "SomeString3"; }
}
Then your Processor could look like this:
public class Processor {
public String method(SuperClass type) {
return (type instanceof CustomInterface) ? ((CustomInterface) type).CustomMethod() : "OK";
}
public static void main(String[] args) {
Processor p = new Processor();
SuperClass obj1 = new SubClass1();
SuperClass obj2 = new SubClass2();
SuperClass obj3 = new SubClass3();
System.out.println(p.method(obj1)); // prints: "SomeString1"
System.out.println(p.method(obj2)); // prints: "OK"
System.out.println(p.method(obj3)); // prints: "SomeString3"
}
}
If you don't understand the ternary operator then you can read about it here That's the condition ? exprTrue : exprFalse syntax. It's a short if else statement basically.
You can create an interface, with default custom method implementation, like:
interface A {
default String customMethod() {
return "";
}
}
And abstract class will implement this interface:
public abstract class SupperClass implements A {
public abstract String getString();
public abstract void method2();
}
Bad design will cause you to get bad answers. If you don't want to cast your object to a child object. You could use reflection.
import java.lang.reflect.Method;
public class Processor {
public String method(SuperClass type) {
Method[] methods = type.getClass().getMethods();
for (Method m : methods) {
if (m.getName().equals("customMethod")) {
try {
return m.invoke(type);
} catch (Exception ex) {
// throw
}
}
}
return "OK";
}
}
Depending on your design you could apply:
if (type instanceof InheritClass2.class) return type.customMethod();
or
if (type.getClass() == InheritClass2.class) return type.customMethod();

What kind of relationship does an interface have with it implementing class?

A subclass has a relationship that is described as IS-A with it base class, but a base class does not share this kind of relationship with it subclass. I was wandering what kind of relationship an interface have with it implementing class since an object of that class can be passed to interface object and the interface object can only access methods defined it concrete Interface.
public class main {
public static void main(String[]args){
Nigeria ng = new Nigeria(){};
//Interface object can accept Nigerias object which is not posible in Inheritance
Continent continent = ng;
//prints Country is in Africa
continent.Africa();
//continent.language(); will not compile language is not in the interface
//Print Democratic thought this should print Undefined since it is inialied with default.
continent.Goverment();
}
}
interface Continent{
public void Africa();
default void Goverment(){
System.out.println("Undefined");
}
}
class Nigeria implements Continent{
#Override
public void Africa(){
System.out.println("Country is in Africa");
}
public void language(){
System.out.println("Official Language is English");
}
public void Goverment(){
System.out.println("Democratic");
}
}
If you are looking for English-language analogues, an Interface is not an "Is a..." nor "Has a..." relationship, but more an "Is...".
An Interface is not about the class that uses it.
It's about the consumer that asks for it.
If you wanted to see it as anything, you could see it as an adjective.
"He is Responsible".
Well, what does he do?
He finishes tasks; he takes ownership of his mistakes; he makes them right.
Is he a pilot, is he a surgeon, is he a doctor?
Is he a child, a father, a greatGrandfather?
Do you care?
I need a responsible person, to help me do this job.
Does ResponsiblePerson inherit from PoliceOfficer? Does Lawyer inherit from ResponsiblePerson, because I'm sure there can be irresponsible lawyers.
class Lawyer extends Person { }
class ResponsibleLawyer extends Lawyer implements ResponsibleEntity { }
class NeedyPerson extends Person {
public void acceptHelp (ResponsibleEntity somebody) {
try {
somebody.attemptTask( someTask );
} catch (TaskCompletionError err) {
somebody.takeOwnership(err);
somebody.fixMistake(err);
}
}
}
Can corporations be Responsible too?
Perhaps we don't see it too often, but it's theoretically possible:
class LawFirm extends CorporateEntity { }
class BetterLawFirm extends LawFirm implements ResponsibleEntity { }
Can somebody be a responsible corporate body? Well, so long as that corporate body does all of the same things that the responsible person would otherwise do, sure.
In another example, you might have a Switchable interface.
Looking at that name, you could surmise that the thing you're being given has a switch which can be poked.
So what methods might it have?
on( )
off( )
toggle( )
isOn( )
sounds like a useful set to have.
What benefit is there to having an interface like this?
Well, now I know that I can deal with a switch, and its lineage doesn't matter.
If all I want is a class which takes a switch and does something with it, why do I need to create dozens of classes, just to accept my dozens of things with switches?
Or override methods into the dirt to do the same.
class SwitchThrower {
public void throwSwitch (CoffeeMaker coffeeMaker) { coffeeMaker.on(); }
public void throwSwitch (LightSwitch lightSwitch) { lightSwitch.on(); }
public void throwSwitch (GhostTrap ghostTrap) { ghostTrap.on(); }
public void throwSwitch (TheHeat theHeat) { theHeat.on(); }
public void throwSwitch (CarIgnition ignition) { ignition.on(); }
}
...
why not just:
class SwitchThrower {
public void throwSwitch (Switchable switch) { switch.on(); }
}
class LightSwitch implements Switchable {
private boolean currentlyOn;
public LightSwitch (boolean initiallyOn) {
currentlyOn = initiallyOn;
}
public LightSwitch () {
currentlyOn = false;
}
public boolean on () {
currentlyOn = true;
return currentlyOn;
}
public boolean off () {
currentlyOn = false;
return currentlyOn;
}
public boolean toggle (boolean forceOn) {
boolean state;
if (forceOn == true) {
state = on();
} else {
state = off();
}
return state;
}
public boolean toggle () {
boolean state;
if (isOn() == true) {
state = off();
} else {
state = on();
}
return state;
}
public boolean isOn () {
return currentlyOn;
}
}
...et cetera
As you can see, aside from describing a basic feature-set of the implementer, interfaces are not about the class at all, but rather the consumer.
An even more awesome implementation of this, in different languages, is _Traits_.
Traits are typically like Interfaces, but they have default behaviour associated with them.
Looking at my Switchable and my LightSwitch, you could imagine that practically all classes with this switch would have the same methods, with the same method behaviour...
...so why would I rewrite all of those methods over again, if I'm already going through the trouble of defining the signature in the interface?
Why couldn't I just add default behaviour in there, and have it apply to the implementer, unless a method is overridden?
Well, that's what Traits / Mix-Ins allow.
The relationship is only the "contract" that the class is getting to implement the methods the interface is offering.
That is how java can separate WHAT objects can do (Interface) and HOW the inherited class will do it.

From Java to C# - Generic cast to BaseClass

i currently have a problem with generics. i want to transfer existing java code into c#. can anybody tell me, how i can do following in c# ?
For example i have a class named module with a generic parameter which inherits from basicdata. i want to add many of this objects to a handler so that they all can be updated in a single method.
in java i have something like this:
public class BasicData
{
}
public abstract class Modul<T extends BasicData>
{
T value;
abstract void update(); // do something with the value
}
public class Handler
{
LinkedList<Modul<?>> modulCollection = new LinkedList<Data<?>>();
void add(Modul<?> m)
{
this.dataCollection.add(m);
}
void update(){
for(Modul<?> d : this.modulCollection){
d.update();
}
}
}
the list should contain various modul-objects, where the value field itself can have various types but they all inherit BasicData.
i searched a while, but i only found exotic solutions. is there no easy way to do the similar thing in c#? i dont want to rewrite my whole design.
at first i thought i could declare the list like this in c#:
LinkedList<Modul<BasicData>> collection;
void add(Modul<BasicData> m)
{
this.dataCollection.add(m);
}
and then add the various objects like this:
class DataImpl : Modul<int>
{
}
handler.add(new DataImpl());
but i found out that you cannot cast this Modul.
is there a solution to do something like that?
thanks in advance,
mick
C# does not have the ? wildcard mechanics as Java has - What is the equivalent of Java wildcards in C# generics, so there is no direct native solution for this problem.
POSSIBLE SOLUTIONS:
1. Use base non-generic class or interface for your Modul:
public abstract class ModulBase : BasicData
{
abstract void update(); // do something with the value
}
public abstract class Modul<T> : ModulBase ...
or
public interface IUpdateable
{
void Update();
}
public abstract class Modul<T> : BasicData, IUpdateable...
And use it like:
public class Handler
{
LinkedList<IUpdateable> modulCollection = new LinkedList<IUpdateable>();
void add<T>(Modul<T> m) // It is generic now
{
this.dataCollection.add(m);
}
void update(){
foreach (IUpdateable d in this.modulCollection){
d.update();
}
}
}
Your Handler.moduelCollection is no longer generic with such an approach, but in any case(even in Java) you would not have been able to access different generics in a simple manner without casting - and that is not the best way to handle different datatypes put into one collection.
You could try the same in C# like below:
public abstract class Module<T> where T : BasicData
{
}
I think I got a solution for you. It kinda uses what others and you said and combines it with something not mention here.
If you have class Foo
class Foo {
public virtual void Method1() {
//Do something
}
public void Method2() {
//Do something
}
//class code
}
Now, you have a class Bar which inherits from Foo
class Bar : Foo {
public override void Method1() {
//Do something
}
public new void Method2() {
//Do something
}
//class code
}
If you declare a variable of the class Bar and try to convert it to Foo, it is completely acceptable and you don't loose any data. However, the next time you want to use the extra properties, methods and variables, you will need to convert it back to Bar. Though, if common members are an override, they should behave as if they were called by a Bar variable, otherwise, if the object is cloned or cast backwards, the common members should behave as if they were called by an Foo instance.
For example:
Bar myBar = new Bar();
Foo myFoo = myBar; //Now myFoo and myBar refer to the same memory address
Foo myFoo2 = myBar.Clone() as Foo; //myFoo2 and myBar do not refer to the same memory address
//These should do exactly the same thing because Method1 is an override
myBar.Method1();
myFoo.Method1();
//These should not do exactly the same thing unless Method2 was not changed in Bar
myBar.Method2();
myFoo.Method2();
//These should do exactly the same thing because Method1 is an override
myBar.Method1();
myFoo2.Method1();
//These should not do exactly the same thing unless Method2 was not changed in Bar
myBar.Method2();
myFoo2.Method2();
Bar myBarConvertedBack = (Bar)myFoo; //No data lost
Now back to the question. Try this:
public abstract class Module<T> where T : BasicData {
protected T value;
public abstract void Update();
public virtual T Value {
get;
set;
}
}
public class Handler
{
LinkedList<Modul<BasicData>> modulCollection = new LinkedList<Data<BasicData>>();
pulic void Add(Modul<BasicData> m)
{
this.modulCollection.add(m);
}
public void Update() {
foreach (Modul<BasicData> d in this.modulCollection)
d.update();
}
}
Consider this class as possible derived class from Module:
public class Class1: Module<BasicData> {
public Class1(BasicData val) {
base.value = val;
}
public override void Update() {
//Do something here
}
public override BasicData Value {
get {
return base.value;
}
set {
base.value = value;
}
}
}
Also see more cases in stackoverflow in the Related or Linked to this question if it is clear. Furthermore, if I'm wrong somewhere correct me

java 8 event listener/dispatcher using lambdas/method references - how to achieve certain things?

I'm trying to write an event engine in Java using the newly added lambdas. I would very much like it if the following code would work:
public class Test
{
public Test()
{
EventEngine.listen(EventType.THIS, self::thisEventCallback);
EventEngine.listen(EventType.THAT, self::thatEventCallback);
EventEngine.listen(EventType.OTHER, (other) -> other.doX());
}
private void thisEventCallback()
{
// do whatever here
}
private boolean thatEventCallback(SomeObject parameter)
{
return parameter.someCheckOrWhatever();
}
}
As far as I understand, I would have to define a generic empty interface, for example, public interface Listener {// nothing here}, and extend it via various other interfaces for each event type so I can specify different parameters and return types where necassary.
Obviously, that would require casting the callbacks to the specific interface inside the EventEngine's trigger method(s), but I have no problem with that.
However, before that I need to find out how to reference these private methods I have defined to the EventDispatcher.listen method. self::thisEventCallback doesn't work. Is there even a way to do this in Java 8 or is it only possible in Scala?
If not, then what would you suggest as a replacement that does not involve creating a new object for every listener/callback?
EventEngine.listen(EventType.THIS, this::thisEventCallback);
EventEngine.listen(EventType.THAT, this::thatEventCallback);
EventEngine.listen(EventType.OTHER, (other) -> other.doX());
So this instead of self.
And you need functional interfaces with one abstract method having the same signature as the callback.
public interface THISInterface {
public void thisEventCallback();
}
public interface THATInterface {
public boolean thatEventCallback(SomeObject parameter)
}
class EventEngine {
public void listen(Type t, THISInterfcace thisCallback) {
thisCallback.thisEventCallback();
}
public void listen(Type t, THATInterfcace thatCallback) {
boolean ok = thatCallback.thatEventCallback();
}
...
}
However there are already many functional interfaces predefined, which you should need to learn. For instance here, one would not need own interfaces.
class EventEngine {
public void listen(Type t, Consumer<Void> thisCallback) {
thisCallback.accept();
}
public void listen(Type t, Predicate<Void> thatCallback) {
boolean ok = thatCallback.test();
}
Whether the above is correct, I am not sure (at the moment deep in java 6 - sigh).
Instead of creating sub-interfaces adding new methods to a base interface you can define a conventional listener interface (like, say MouseListener) having multiple call-back methods and create sub-interfaces overriding all but one method with empty default methods for the sole purpose of allowing lambda implementations of the remaining single abstract method. They replace what classes like MouseAdapter did for previous Java versions (when using anonymous inner classes):
interface AllPurposeListener {// the only one our engine uses internally
void caseOne(int arg);
void caseTwo(String arg);
}
interface CaseOneListener extends AllPurposeListener {
#Override public default void caseTwo(String arg) {}
}
interface CaseTwoListener extends AllPurposeListener {
#Override public default void caseOne(int arg){}
}
// Of course, I over-simplify the engine’s listener registry here
AllPurposeListener listener;
public void listen(AllPurposeListener l) {
listener=l;
}
public void listen(CaseOneListener l) {
listener=l;
}
public void listen(CaseTwoListener l) {
listener=l;
}
private void foo(int i) { }
private void bar(String s) { }
void doRegistration() {
listen(this::foo);// register for case one
listen(this::bar);// register for case two
listen(new AllPurposeListener() { // for all cases
public void caseOne(int arg) {
}
public void caseTwo(String arg) {
}
});
}

Categories