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

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.

Related

Polymorphic uncurried method calls (adhoc polymorphism) in Java

Let me start with an example.
Say I have an abstract Vehicle class.
public abstract class Vehicle {
public Vehicle() {}
public abstract void ride();
}
And classes Car and Bicycle that inherit from this abstract class.
public class Car extends Vehicle {
public Car() {}
#Override
public void ride() {
System.out.println("Riding the car.");
}
}
public class Bicycle extends Vehicle {
public Bicycle() {}
#Override
public void ride() {
System.out.println("Riding the bicycle.");
}
}
When I apply the ride() method to an object of type Vehicle whose actual type can only be determined at runtime, the JVM will apply the correct version of ride().
That is, in a curried method call of the sort v.ride(), polymorphism works the expected way.
But what if I have an external implementation in form of a method that only accepts a subtype of Vehicle as an argument? So, what if I have repair(Bicycle b) and repair(Car c) methods? The uncurried polymorphic method call repair(v) won't work.
Example:
import java.util.ArrayList;
import java.util.List;
public class Main {
private static void playWithVehicle() {
List<Vehicle> garage = new ArrayList<Vehicle>();
garage.add(new Car());
garage.add(new Car());
garage.add(new Bicycle());
garage.forEach((v) -> v.ride()); // Works.
garage.forEach((v) -> {
/* This would be nice to have.
repair(v.castToRuntimeType());
*/
// This is an ugly solution, but the obvious way I can think of.
switch (v.getClass().getName()) {
case "Bicycle":
repair((Bicycle) v);
break;
case "Car":
repair((Car) v);
break;
default:
break;
}
});
}
private static void repair(Bicycle b) {
System.out.println("Repairing the bicycle.");
}
private static void repair(Car c) {
System.out.println("Repairing the car.");
}
public static void main(String[] args) {
playWithVehicle();
}
}
I have to check for the class name and downcast. Is there a better solution to this?
Edit: My actual purpose is that I'm traversing an abstract syntax tree and I happened to notice that I want double dispatch.
Ast is an abstract class from which actual AST nodes like Assign, MethodCall, or ReturnStmt inherit. body is a polymorphic list of Asts.
Code snippet:
List<Ast> body;
body.parallelStream().forEach((ast) -> {
// This one won't work.
visit(ast);
// This one will work.
if (ast instanceof Assign) {
visit((Assign) ast);
} else if (ast instance of MethodCall) {
visit((MethodCall) ast);
} else if (ast instance of ReturnStmt) {
visit((ReturnStmt) ast);
}
// etc. for other AST nodes
});
private void visit(Assign ast) {
}
private void visit(MethodCall ast) {
}
private void visit(ReturnStmt ast) {
}
My only possibilities of achieving double dispatch is either checking the class and downcasting or properly implementing the visitor pattern, right?
Answer: There is no multiple dispatch in Java and it can be simulated by instanceof or by the visitor pattern.
See here:
Java method overloading + double dispatch
See also here: https://en.wikipedia.org/wiki/Multiple_dispatch#Examples_of_emulating_multiple_dispatch
On a sidenote, exactly this is possible in C# with dynamic calls: How to build double dispatch using extensions
And this is also possible in the many languages that are compiled to JVM bytecode, e.g. Groovy was mentioned.

Avoid casting and instanceOf

I got an interface
public interface Details {
// nothing needed until now
}
which is used in a class like the following:
public class Value {
// many fields
private Details details;
public Value(SomeType type) {
switch (type) {
case TYPE_1:
case TYPE_2:
this.details = new DetailsA();
break;
case TYPE_3:
this.details = new DetailsB();
break;
default:
throw new NotImplementedException("not yet implemented");
}
}
public Details getDetails() {
return this.details;
}
}
The interface has two implementations
public class DetailsA implements Details {
private BigDecimal betragA;
public DetailsA() {
}
public BigDecimal getBetragA() {
return this.betragA;
}
public void setBetragA(BigDecimal betragA) {
this.betragA = betragA;
}
}
public class DeailsB implements Details {
private BigDecimal betragB;
private boolean booleanB;
public BetragB() {
}
public BigDecimal getBetragB() {
return this.betragB;
}
public void setBetragB(BigDecimal betragB) {
this.betragB = betragB;
}
public boolean isBooleanB() {
return this.booleanB;
}
public void setBooleanB(boolean booleanB) {
this.booleanB = booleanB;
}
// some more fields
}
I got a model class in which I want to use those details, depending on the instance.
public class Model extends AbstractModel {
private Details details;
public void init(StoerungValue stoerung) {
setDetails(stoerung.getSchaden().getDetails());
}
private void setDetails(Details details) {
this.details = details;
}
// ...
In there I have some operations like the following
// ...
public void setBooleanB(boolean booleanB) {
if (details instanceof DetailB) {
((DetailB) details).setBooleanB(booleanB);
}
}
// ...
How can I avoid this casting and instanceOf stuff? Is any of the design patterns applicable here?
I think the problem you have here is a collection of design smells. You've painted yourself into a corner, and there may not be an easy way out. I don't know if this solution will work for you or not, but you can at least consider this.
The first design smell is that you have created an inheritance relationship where none actually exists. In short, the hierarchy rooted at Details violates the Liskov Substitution Principle. When a class claims (as Model does) to support the Details interface, it's making the claim that any implementation of Details will do. The program's correctness and behavior shouldn't change whether it's given a DetailsA, a DetailsB, or some FooDetails class that hasn't even been invented yet.
The reality is that DetailsA and DetailsB are not actually related. You can see this because Details has no methods, and thus may as well be Object which any two classes already inherit from.
The second design smell is "Feature Envy." It seems that many methods of Model are just pass-through calls to its underlying details property. You could consider, rather than having setBooleanB on Model to just provide a getDetails method, and then let the caller work directly on the Details object. This won't remove the instanceof checks or casting, but it will move them out of this class.
The third thing here is related two the first two. Model depends not on Details as its property types would tell you, but rather on (at least) DetailsB. If that's the case, then its property type should say so. Now, it's possible that sometimes you need a Model with a DetailsA and sometimes you need a Model with a DetailsB, but it can't be both at the same time. In that case, you can work around the issue with generics.
First, make the Model class generic, with a type parameter that tells what its underlying Details must actually be.
public abstract class Model<T extends Details> {
private T details;
public void init(T dets) {
setDetails(dets);
}
public void setDetails(T dets) {
this.details = dets;
}
public T getDetails() {
return this.details;
}
}
Then, create two subclasses that are bound to different Details types, and can thus promise to do the right thing without requiring casting or instanceof calls.
public class ModelA extends Model<DetailsA> {
public BigDecimal getBetragA() {
return this.getDetails().getBetragA();
}
}
public class ModelB extends Model<DetailsB> {
public boolean getBooleanB() {
return this.getDetails().isBooleanB();
}
public void setBooleanB(boolean boolB) {
this.getDetails().setBooleanB(boolB);
}
}
I'm not sure if that'll fix your problem or not, but it's something to consider.

Using Generalization properly

Suppose you have the following Interfaces
public interface Action {
public State execute(State state);
}
public interface State {
public Collection<Action> getPossibleActions();
}
And this method
public static Collection<State> getAllSuccessorStates(State state){
Collection<State> allSuccessors = new HashSet<>();
for (Action action: state.getPossibleActions()){
State successorState = action.execute(state);
allSuccessors.add(successorState);
allSuccessors.addAll(getAllSuccessorStates(successorState));
}
return allSuccessors;
}
A Concrete State could be for example a Chessboard and an Action the movement of a Piece on the board. Obviously the Chess-Actions need to know the concrete State class:
public class ChessAction implements Action {
#Override
public ChessState execute(ChessState state) {...}
}
Which is ofcourse not an allowed way of overriding execute. What would be the correct way of implementing this, so you can have concrete Actions, that operate on concrete States, which you can give as Arguments to getAllSuccessorStates?
I thought about Generics and also got answers pointing to Generics, but that brings about new Problems. If i write the Action class like this:
public interface Action<E extends State> {
public E execute(E state);
}
i will have the following Problem with ChessState class:
#Override
public Collection<Action<State>> getPossibleActions() {
Collection<Action<State>> actions = new ArrayList<>();
actions.add(new ChessAction());
return actions;
}
the line Actions.add causes the following error: The method add(Action) in the type Collection> is not applicable for the arguments (ChessAction)
Now i could declare Actions as
Collection<Action<ChessState>> actions = new ArrayList<>();
but that wont be a permitted return type.
You can use generics (needs java 1.5 or above):
public interface Action<T extends State> {
public T execute(T state);
}
public class ChessAction implements Action<ChessState> {
#Override
public ChessState execute(ChessState state) {...}
}
Hope that helps.
i found a satisfactory Solution now, which works correctly, doesnt need instanceof and yields no compile warnings:
public interface Action<E extends State<?>> {
public E execute(E state);
}
public interface State<E extends Action<?>> {
public Collection<E> getPossibleActions();
}
public static <A extends Action<S>, S extends State<A>> Collection<S> getAllSuccessorStates(S state){
Collection<S> allSuccessors = new HashSet<>();
for (A localAction: state.getPossibleActions()){
S successorState = localAction.execute(state);
allSuccessors.add(successorState);
allSuccessors.addAll(getAllSuccessorStates(successorState));
}
return allSuccessors;
}
Example of using getAllSuccessorStates (i forgo the implementation Details of the concrete classes here, but the Point should be apparent. You can use the method getAllSuccessorStates with any concrete State class, get Instances of this class in return collection and use them)
public class TestState implements State<TestAction> {...}
public class TestAction implements Action<TestState> {...}
public static void main(String[] args) {
TestState initialState = new TestState("1");
Collection<TestState> allSuccessorStates = getAllSuccessorStates(initialState);
for (TestState state: allSuccessorStates){
System.out.println(state.getStateStr());
}
}
This Question arose from the book "AI-A modern approache" by Stuart Russel and Peter Norvig, in case somebody who reads this book has the same Problem and searches for solutions. In the book the Action and State methods are inside a Problem Class, but i think in this way the OO-design is better.
Well, ChessState must have the same signature of execute as in the Action interface. If you require that ChessAction.execute accept only ChessState, you can write :
public class ChessAction implements Action {
#Override
public State execute(State state)
{
if (!(state instanceof ChessState))
throw new SomeException ();
ChessState cs = (ChessState) state;
...
}
}
You need to implement the same inherited method, and it will work since State is a super class for CheesState.
public class ChessAction implements Action {
#Override
public State execute(State state) {...}
}
Inside the execute method, you can use polymorph method (define in State and redefined ChessState), or you can cast to ChessState (ChessState s = (ChessState) state;), then use it as you need

Techniques to expose multiple Interfaces (via static creation methods)

I am currently working on a project where I am attempting to hide as much detail about a hierarchy I have created as possible. I want to do this to minimize the amount of information the user needs to know about objects (and to control what they can do to the state of the object). In addition, I'm using the pattern to limit what kinds of objects the application can make, and limit it to creation from the factory.
The main issue I am having, however, is that there are a few different kinds of interfaces I would like to expose. Each interface is has additional functionality that I don't believe should be shared, and I would like to keep these interfaces separated. Finally, I don't know what new interfaces may come in the future, but I'd like to try and be ready for them.
Weapon:
public interface Weapon extends GameObject {
Number attack();
boolean addWeaponAttribute(WeaponAttribute attribute);
}
Firearm:
public interface Firearm extends Weapon {
void reload(Number rounds);
}
My question is what would be the best way to have the factory produce objects with different interfaces? Here's what I am thinking "the best would be":
The most clear to the user (it's obvious what they're asking for and what they're getting back)
The best for future expansion (I am uncertain what new interfaces I will be adding to this system).
Here's what I have been thinking so far:
Create properly named methods for each interface
public static Firearm getFirearm(String firearmName) {
...
}
public static Weapon getWeapon(String weaponName) {
...
}
Do the above, but produce the factories in separately named classes
public class WeaponFactory {
public static Weapon getWeapon(String weaponName) {
...
}
}
public class FirearmFactory {
public static Firearm getFirearm(String firearmName) {
...
}
}
Something completely different
I'm open to suggestions, and changes. This is a flexible project, so I can change as much as I want to (in terms of this portion of the project) to make a better result.
Also - As a side note, I was uncertain if this question was too open-ended or not for SO. If I made a mistake posting here, let me know and I'll move my question elsewhere.
What I can suggest is to make the interfaces as concise as possible and move other unrelated methods elsewhere. you might consider doing this for example:
public interface Weapon extends GameObject {
Number attack();
}
public interface Modifiable extends GameObject {
boolean addWeaponAttribute(WeaponAttribute attribute);
}
public class ActualWeapon implements Weapon, Modifiable {
...
}
Then you can create different factories to generate your concrete objects, as you already mentioned:
public class WeaponFactory {
public static Weapon getWeapon(String weaponName) {
...
}
}
or
public class GenericFactory<T extends GameObject> {
public T createGameObject(Object... properties) {
...
}
}
public class WeaponFactory extends GenericFactory<ActualWeapon> {
public ActualWeapon createGameObject(Object... properties) {
...
}
}
I think you can't add static methods to interfaces. I wouldn't recommend it if you even could.
maybe just use the factory method design pattern like
interface GameObject {}
class WeaponAttribute {}
interface Weapon extends GameObject {
Number attack();
boolean addWeaponAttribute(WeaponAttribute attribute);
}
interface Firearm extends Weapon {
void reload(Number rounds);
}
class WeaponBaseClass implements Weapon {
WeaponBaseClass(WeaponName weaponName) {
this.weaponName=weaponName;
}
#Override public Number attack() {
return null;
}
#Override public boolean addWeaponAttribute(WeaponAttribute attribute) {
return false;
}
public String toString() {
return weaponName.toString();
}
final WeaponName weaponName;
}
class FirearmBaseClass extends WeaponBaseClass implements Firearm {
public FirearmBaseClass(WeaponName weaponName) {
super(weaponName);
}
#Override public void reload(Number rounds) {}
}
enum WeaponName {
knife, sword, colt45, glock19, glock19WithLaser;
}
class WeaponCreator {
Weapon create(WeaponName weaponName) {
switch (weaponName) {
case knife:
case sword:
return new WeaponBaseClass(weaponName);
case colt45:
case glock19:
return new FirearmBaseClass(weaponName);
default:
return new WeaponBaseClass(weaponName);
}
}
}
class FancyWeaponCreator extends WeaponCreator {
Weapon create(WeaponName weaponName) {
Weapon weapon = null;
switch (weaponName) {
case glock19WithLaser:
weapon = super.create(WeaponName.glock19);
// whatever it needs
return weapon;
default:
return new WeaponBaseClass(weaponName);
}
}
}
public class Main {
public static void main(String[] args) {
System.out.println(new WeaponCreator().create(WeaponName.knife));
System.out.println(new WeaponCreator().create(WeaponName.colt45));
System.out.println(new FancyWeaponCreator().create(WeaponName.glock19WithLaser));
}
}
What about a factory of factories? Each factory would implement ifactory. Ifacorty would require a method Instantiate(string type) and return your subclassed weapon instance.
Using generics, you might only need one factory method like:
public <T> T getObject(java.lang.Class<T> responseType, String name)
Then the user would call:
Weapon weapon = factory.getObject(Weapon.class, "my weapon");

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

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.

Categories