I am trying to design an abstract class which will enforce implementation of an instance variable even though the type if this instance variable is unknown at the abstract level. For example:
public abstract class AbstractDiet{
abstract void computeMeat()
abstract void computeVeggies()
…
}
public abstract class AbstractAnimal{
protected AbstractDiet diet;
…
}
Then I'd like users to implement something like:
public class Cat extends AbstractAnimal{
protected CatFoodDiet diet; // CatFoodDiet extends AbstractDiet
…
}
Is this the best way to implement the diet variable? I want to ENFORCE that a subclass of AbstractDiet is always implemented in a subclass of AbstractAnimal.
First of all: Keep your instance variables private, and provide accessor methods.
Second of all: It sounds like you are trying to define an interface. Use an interface any time you want to say something like, "every animal has a diet."
interface Animal {
Diet getDiet();
...
}
If you like, you can also incorporate Bohemian's idea, and make it generic.
interface Animal<D extends Diet> {
D getDiet();
...
}
That way, you will have maximum freedom when it comes time to define different kinds of animal
class Cat implements Animal<CatDiet> {
CatDiet getDiet() { return...; }
}
You can't (and shouldn't) approach the design like that. Using abstract classes, try something like this:
public abstract class AbstractDiet {
abstract void compute();
}
public abstract class AbstractAnimal<T extends AbstractDiet> {
protected T diet;
}
public class CatFoodDiet extends AbstractDiet {
compute() {
//
}
}
public class Cat extends AbstractAnimal<CatFoodDiet> {
// use field in super which is type CatFoodDiet
}
But typically you would use interfaces instead of abstract classes for the abstract types.
The most flexible way is to just require the subclass to provide the information:
public abstract class AbstractAnimal {
// Subclasses must provide a function that returns the diet
public abstract AbstractDiet getDiet();
}
public class PetRock extends AbstractAnimal {
#Override
public AbstractDiet getDiet() {
return new SunlightDiet();
}
}
If you want to force a particular implementation, this is a common way:
public abstract class AbstractAnimal {
private AbstractDiet diet;
// Provide a constructor that sets a diet
protected AbstractAnimal(AbstractDiet aDiet) {
if (null == aDiet)
throw new NullPointerException("Diet must be specified");
diet = aDiet;
}
public class PetRock extends AbstractAnimal {
public PetRock() {
// Subclasses have to provide a diet to the superclass
super(new SunlightDiet());
}
}
Related
Quick style question:
I have a Java interface that defines functions that must be implemented by classes in a particular hierarchy, all descended from a specific base class.
There are contexts where I will be dealing with these classes through a pointer to the interface, but I need a pointer to the base class instead.
Example:
public class Base {}
public interface ChildRequirements {
Base asBase();
}
public class Child extends Base implements ChildRequirements {
Base asBase() { return this; }
}
public class SomeClass {
public void doSomething(Base base) { }
public void doSomethingElse(ChildRequirements creqt) {
doSomething(creqt.asBase());
}
}
Is this bad form? Am I thinking about this the wrong way? Should I just cast creqt as Base and ignore the warnings?
I have a Java interface that defines functions that must be implemented by classes in a particular hierarchy, all descended from a specific base class.
Then it isn't an interface, it's an abstract base class. Get rid of ChildRequirements and instead have Base define the requirements and mark it abstract:
abstract public class Base {
// ...required methods here, `abstract` if you don't have a
// base implementation...
}
public class Child extends Base {
// ...implements any `abstract` methods...
}
public class SomeClass {
public void doSomething(Base base) { }
public void doSomethingElse(Base creqt) {
doSomething(creqt);
}
}
But whenever possible, program to interfaces, not abstract classes.
I don't see the difference between your typing and just using interfaces and ol'regular inheritance. Your return this in the Child class seems to suggest you expect it to be a subtype of Base. The way the interfaces are structured it seems like you are actually expressing an is-a relationship between Base and ChildRequirements, but decorating the super class.
Alternate typing:
//Straight-forware inheritance
public interface Base {
}
interface ChildRequirements extends Base{
Base asBase();//return the super
}
class Child implements ChildRequirements {
public Base asBase() { return this;}
}
class SomeClass {
public void doSomething(Base base) { }
public void doSomethingElse(ChildRequirements creqt) {
doSomething(creqt.asBase());
}
}
I went to an interview. Interviewer asked me if one can instantiate an interface and abstract class? As per my knowledge I said "No". But he said "Yes, we can with the help of an anonymous class".
Can you please explain to me how?
This was a trick questions.
No you can not instantiate an interface or abstract class.
But you can instantiate an anonymous class that implements/extends the interface or abstract class without defining a class object. But it is just a shortcut to defining a fully named class.
So I would say technically your answer was correct.
I don't know what is "instantiation of interface and abstract class".
I think it's an inaccurate, improper expression of something,
we can only guess at the intended meaning.
You cannot create an instance of an interface or an abstract class in Java.
But you can create anonymous classes that implement an interface or an abstract class.
These won't be instances of the interface or the abstract class.
They will be instance of the anonymous class.
Here's an example iterator from the Iterator interface that gives you an infinity of "not really":
new Iterator<String>() {
#Override
public boolean hasNext() {
return true;
}
#Override
public String next() {
return "not really";
}
};
Or a funky AbstractList that contains 5 "not really":
List<String> list = new AbstractList<String>() {
#Override
public int size() {
return 5;
}
#Override
public String get(int index) {
return "yes";
}
};
Assume you have an abstract class: MyAbstractClass with abstract void method myAbstractMethod. Then you can make an "instance" of this class via this code:
MyAbstractClass myAbstractClassInstance = new MyAbstractClass() {
public void myAbstractMethod() {
// add abstract method implementation here
}
};
myAbstractClassInstance extends your MyAbstractClass in this case. When you instantiate this class you have to implement all abstract methods as you can see from the code above.
The same way works for interfaces, assume you have an interface MyInterface with a void method myInterfaceMethod inside, then you can create an "instance" (implementation of this instance) via this code:
MyInterface myInterfaceImpl = new MyInterface() {
public void myInterfaceMethod() {
// add method implementation here
}
}
myInterfaceImpl is an implemetation of MyInterface in this case. When you create an object using interface, you have to implement interface methods as it is shown above.
Interface :
interface Interface1 {
public void m1();
}
When you right
new Interface1() {
public void m1() {
}
}
Its not actually creating the instance of Interface. Its creating an instance of its subtype which doesnt have any name/reference. Hence we cannot create an instance of interface or abstract class
You cannot create instances of abstract classes or interfaces using the new operator. For example,
new AbstractSet(); // That's wrong.
You can, however, use them to declare reference variables. For example, You can do this:
AbstractSet set;
You can instantiate anonymous as well as declared implementing classes or subclass.
For example, Set extends AbstractSet, so you can instantiate Set.
Yes, we can create by having defining the abstract methods or the interface methods on the fly during instantiation. That's like a Named anonymous class.
//interface
Runnable r = new Runnable(){
public void run() {
System.out.println("Here we go");
}
};
//Abstract class
abstract class MyAbstract {
abstract void run();
}
MyAbstract ab = new MyAbstract(){
#Override
void run() {
System.out.println("Here we go");
}};
I am doing an exercise, the book is not helping me grasp the concept, neither are the online resources. This may seem really silly but I don't know what I'm missing!!! I am quite new to Java and have had a look at other examples on stack but to no avail :s I need to declare 3 interfaces. Each interface needs to declare a method with the same name as its interface. Then the abstract class is extended by 3 classes which implement the aforementioned interfaces.Each class needs to be instantiated. If anyone could explain the procedure to this I would be eternally grateful.
interface antiLockBrakes{
public void antiLockBrakes();
}
interface cruiseControl{
public void cruiseControl();
}
interface powerSteering{
public void powerSteering();
}
public abstract class Auto{
abstract class Model1 extends Auto implements antiLockBrakes{
public abstract void antiLockBrakes();
Model1 mod1 = new Model1();
mod1.antiLockBrakes();
}
public static void main(String[] args){
}
}
this is your question: someone to explain how exactly to declare and interface and then have it implemented in the abstract class right??
Here's the answer for it.
See lets consider I have an interface
interface someInterface{
public void someMethod();
}
Now to implement the someInterface in abstract class
public abstract class SomeClass implements someInterface{
public void someMethod(){
System.out.println("Inside someMethod");
}
public abstract myMethod();
}
See in the class SomeClass we have implemented interface by giving definition to method someMethod() and since we want this SomeClass to be a abstract class we have defined one abstract method myMethod() for it.
Now any class which extends from SomeClass will also implement interface someInterface implicitly (because SomeClass has implemented it) and if it want its own definition for someMethod() it can override it. But if a child class wants to be a concrete class ( a class in which all its method will have implementation) then it has to provide implementation for abstract method myMethod().
HTH:)
this is what I like to use to see the difference between abstract classes and interface classes
interface class
//I say all motor vehicles should look like that :
interface MotorVehicle {
void run();
int getFuel();
}
// my team mate complies and write vehicle looking that way
class Car implements MotorVehicle {
int fuel;
public void run() {
System.out.println("Wrroooooooom");
}
public int getFuel() {
return this.fuel;
}
}
abstract class
// I say all motor vehicles should look like that :
abstract class MotorVehicle2 {
int fuel;
// they ALL have fuel, so why let others implement that ?
// let's make it for everybody
int getFuel() {
return this.fuel;
}
// that can be very different, force them to provide their
// implementation
abstract void run();
}
// my team mate complies and write vehicle looking that way
class Car2 extends MotorVehicle2 {
void run() {
System.out.println("Wrroooooooom");
}
}
Java allows to assign subclass instances to class-typed fields, for example:
public class BaseClass {
}
public class SubClass extends BaseClass {
}
public class Example {
private BaseClass field1;
public void assign(SubClass subclass) {
field1 = subclass; // is OK
}
}
Java allows also to use interfaces as types. If we have an interface Fooable,
public interface Fooable {
void foo();
}
our Example class can have a field of type Fooable,
Fooable field2;
That is, it is possible to assign to field2 an instance of any class implementing Fooable interface.
But what if I want to tell the compiler that field3 has to be both an instance of BaseClass and implementation of Fooable interface? So that, if there is a class
public class FooSubClass extends BaseClass implements Fooable {
#Override
public void foo() {
// TODO
}
}
, I could assign to field3 instances of FooSubClass but not of SubClass?
Is it possible without using generics of any sort?
You can't do it like you are trying to.
You would need to define another class, perhaps an abstract class would suit you here:
public class abstract AbstractSubClass extends BaseClass implements Fooable {
...
}
Then FooSubClass:
public class FooSubClass extends AbstractSubClass {
...
}
Then your field is:
private AbstractSubClass field1;
Which will accept FooSubClass but not SubClass
Its the only way the compiler can guarantee that field1 will actually have implementations of all the required methods.
Here is a textbook example to illustrate:
public class Bird() {
public void eat() {
....
}
}
public interface FlyingBehaviour() {
void fly();
}
public abstract class FlyingBird extends Bird implements FlyingBehaviour() {
...
}
public class Eagle extends FlyingBird {
...
}
public class Penguin extends Bird {
...
}
FlyingBird bird = new Eagle();
bird.fly();
FlyingBird bird = new Penguin(); //Compilation Error - Penguins cant fly!
There is no way in java to ensure a object field inherits/implements two different classes.
Assuming you have control of all the objects here, the easiest fix would be for your base class to implement Fooable.
Since you are using a assign-method for setting the fields, you can check if it is correct type of object using instanceof in that method.
public void assign(BaseClass baseClass) {
if (baseClass instanceof foo)
field3 = baseClass;
}
You may throw an exception if class not implementing foo is provided.
edit:
Doh, didn't see that the fix should be for compile-time.
I have classes A, B with B extends A
I have interface defined as
public interface MyProcessor<EVENT> {
void processEvent(EVENT event);
}
I have two implementations
public class EventAProcessor implements EventProcessor<A> {
#Override
public void processEvent(A a) {
}
public class EventBProcessor implements EventProcessor<B> {
#Override
public void processEvent(B b) {
}
there is common processing so I decided to extend BProcessor from Aprocessor
public class EventBProcessor extends EventAProcessor implements EventProcessor<B> {
}
This is where it fails with the message
MyProcessor cannot be inherited with different arguments: <A> and <B>
I have other solutions to workaround my problem, but just wondering, how to get this working.
Don't make EventBProcessor extend EventAProcessor as it's not an is-a relationship. Reuse the functions you need either by pulling them into a common abstract class, or in a separate helper class that you reuse by composition. It's not always the best option to reuse through inheritance.
You should introduce an abstract generic class:
public abstract class AbstractEventProcessor<EVENT>
implements EventProcessor<EVENT> {
// Put your common logic here
}
Your other classes will then inherit common functionality as such:
public class EventAProcessor extends AbstractEventProcessor<A> {}
public class EventBProcessor extends AbstractEventProcessor<B> {}
This doesn't necessarily have to do with generics. It's a general way to approch polymorphism in object-oriented programming.
If you want to reuse code through inheritance, the following should be OK:
public abstract AbstractEventAProcessor<T extends A> implements EventProcessor<T> {
// common methods
}
public class EventAProcessor extends AbstractEventAProcessor<A> {
#Override
public void processEvent(A a) { ... }
}
public class EventBProcessor extends AbstractEventAProcessor<B> {
#Override
public void processEvent(B b) { ... }
}
I don't see how the interface has anything to do with either of your implementations. Neither of them implements the MyProcessor interface.
You also don't show any hierarchy for the Event class. What makes you think you can have different Event types with this arrangement?
Here's how I might do it:
public interface Event {
String getName();
}
public interface EventProcessor<T extends Event> {
void process(T event);
}
You don't need different EventProcessor implementations this way - the generic should be able to differentiate between different Event types. You'll only need a custom implementation if the process() method needs to change by type. You might way to think about a Visitor pattern if it does.
Add a shared "common" generic ancestor that requires A or a subclass thereof.
public abstract class ACommonProcessor<AEvent extends A> implements MyProcessor<AEvent> {
...
// shared code goes here
}
public class EventBProcessor extends ACommonProcessor<B> {
...
// B-specific code goes here
}
public class EventAProcessor extends ACommonProcessor<A> {
...
// etc
}