Okay, so, for example, let's say I have an abstract class called "Vehicle". The Vehicle class, has, among other things, a static variable called wheels, which is not initialized. What I want to do is have other subclasses extending from the Vehicle class, like "Motorcycle", and "Truck", and in these subclasses, have the wheels initialized.
Code:
public abstract class Vehicle {
static int wheels; //number of wheels on the vehicle
}
But the below doesn't work:
public class Motorcycle extends Vehicle {
wheels = 2;
}
Is there a way to do this effectively?
EDIT:
Thank you to all the people who replied so far. I get that making instances is probably a better way to go than to put them all in separate classes, but I don't get the "static" part of java perfectly, so I need a little help here.
What I'm trying to do for my program is have separate sprites for the Motorcycle and Truck classes, and I want them to be static so that I won't have to reload the image every time I create an instance of a Motorcycle or Truck. Other than that, though, they'll have almost identical properties to each other, which is why they'll both be extending from the Vehicle superclass.
The only other way I can see this being done is by just not declaring the sprite variable at the Vehicle class, but at the Motorcycle/Truck class, like below:
public abstract class Vehicle {
//Other coding
}
public class Motorcycle extends Vehicle {
static BufferedImage sprite = //initialize image
//Other coding
}
public class Truck extends Vehicle {
static BufferedImage sprite = //initialize image
//Other coding
}
If 'wheels' is static, there is only one and it will apply to all vehicles at the same time. So tricycle, a motorcycle, an 18-wheeler truck and a Ford will all have the same number of wheels.
That doesn't make sense to me. It would be better to have 'wheels' be an instance variable that is in the parent class but each subclass sets appropriately.
But you can try
Vehicle.wheels = 2;
NOTE: I'm adding to my answer since you added to your question.
I like your idea of having statics in each of the subclasses. But you should make them private. Then put an abstract method in the parent class (Vehicle) like
public abstract BufferedImage getSprite();
Then each direct subclass has to have the same method and it can return the private static variable.
Make the variable static so you only have to load them once. Make them private so that code outside the class itself can't fool with it and introduce bugs. You could make them 'final' if possible so the code in the class itself can't change it after the fact and introduce bugs. (A 'final' variable can't have its value changed but the contents of its value can change. So 'final' isn't a wonderful as it could be.)
What you're trying to do is fundamentally flawed. You could make Motorcycle initialize wheels once:
// Static initializer
static
{
wheels = 2;
}
... or each time an instance was created:
// Instance initializer
{
wheels = 2;
}
But there's just one variable - not one for Motorcycle, one for Truck etc. If you did the same thing for both Truck and Motorcycle, then whichever is initialized last would "win".
It's not clear how you want to use this field anyway - but if you just have a single static field, then that's just going to have a single value - not one per subclass.
Static members are only defined once and are common to every extending class. Changing the value in one of them will affect all of the others.
This is what I believe you really want to achieve:
public abstract class Vehicle {
private int _wheels; //number of wheels on the vehicle
public int getWheels(){return _wheels;}
protected Vehicle(int wheels){
_wheels = wheels;
}
}
public class Motorcycle extends Vehicle {
public Motorcycle(){
super(2);
}
}
public class Car extends Vehicle {
public Car(){
super(4);
}
}
I think there's a significantly more elegant way to do this
What I am about to propose still suffers from the limitation that you need an instance. I don't see any way around that because you want wheels to be exposed as part of the superclass, but the value of wheels is dependent on the subclass and inside of Vehicle there is no notion of a subclass type without an instance.
In my opinion, 'wheels'in this case is neither a static or non-static property. It is class metadata. And the Java way to specify class metadata is via annotations.
What you need is a user-defined annotation like this:
#Documented
#Retention(RetentionPolicy.RUNTIME)
public #interface VehicleMetadata{
int wheels();
}
You then annotate Motorcyle as follows:
#VehicleMetadata(2)
public class Motorcycle extends Vehicle {}
In the superclass you provide an accessor that gets the value of the annotation property. I would recommend you use a "lazy evaluation" approach so you don't use reflection every time you need the value.
Note the use of this to get the instance:
private String wheelsValue;
public String getWheels() {
if (this.wheelsValue== null) {
VehicleMetadatane = null;
for (Annotation annotation : this.getClass().getAnnotations()) {
if (annotation instanceof VehicleMetadata) {
ne = (VehicleMetadata) annotation;
break;
}
}
wheelsValue = ne.wheels();
}
return wheelsValue ;
}
In my opinion, this is the most elegant solution.
The original class declaration:
public abstract class Vehicle {
static int wheels; //number of wheels on the vehicle
}
public class Motorcycle extends Vehicle{...}
public class Truck extends Vehicle{...}
does not work because the static variable goes with the class it was declared in. Static class variables create memory storage for only one instance of the variable per class and not per class object. When the compiler (jvm) sees the static variable in the class Vehicle it allocates memory to that variable and that memory location is static (does not change). Each subsequent use of the Vehicle class whether it is extended or instantiated as an object will point to the same location in memory for the static variable.
In order to use the static variable in the child classes you have to use it inside a method. So, you could in essence re-write your Motorcycle class like this:
class Motorcycle extends Vehicle{
public Motorcycle(){
wheels = 2;
}
}
and it will compile; however, you will may not get the results you expect. For example if you do this in your code (assuming Truck class is declared like Motorcycle class and assigns 4 to wheels and there is a getter method to return the value of wheels).
Motorcycle cycle = new Motorcycle();
Truck pickup = new Truck();
...
System.out.println("Motorcycle has " + cycle.getWheels() + " wheels.");
will print:
Motorcycle has 4 wheels.
If you make a static variable in your objects it will be the same for every Vehicle class you will make, even when you would make another subclass for your abstract Vehicle class. This because of the "nature" of any static variable.
I think you want to use a non-static variable so that for every instance of any subclass of the abstract Vehicle class you can determine the value of the wheels and that is done as following:
public abstract class Vehicle {
public int wheels; //number of wheels on the vehicle
}
and any subclass:
public foo extends Vehicle{
public void someMethode(){
this.wheels = 2;
}
}
You could also do this for the static variable but then you will change it for every instance of any subclass of Vehicle
Hope i helped you
Maybe you'd like to think about the constructors you are using.
public Vehicle(int wheels) {
this.wheels = wheels;
}
public Motorcycle(int wheels) {
super(wheels);
}
public Motorcycle cycle = new Motorcycle(2);
The Motorcycle uses the super constructor that knows what to do with the parameter. It automatically sets wheels to 2.
Related
Im trying to implement an interface that should affect some objects of a class but not others.
For example lets say this is my code:
public interface KnowsHowToSwim{
double getHowFast();
}
public class Stable{
Horse pinky = new Horse(veryFast);
Horse lightning = new Horse(veryPretty){
#Override
public float getPrettynessFactor(){
return super.getPrettynessFactor()*10000000000
}
};
Horse wetty = new Horse(soCool); <-- This one should KnowHowToSwim
}
Now, i know I can create a new class that extends horse and implements KnowHowToSwim, but since my application will have a lot of fields from different classes that will implement that interface, I was wondering if there was a way to implement the interface in a specific object similar to how Horse lightning overrides its method.
No you can't.
You wan't something like a trait or mixin, which is not supported in Java.
Java8's default methods in interfaces won't work for you because you need a property in the instance (or access to the instance), which is not possible. Default methods have no reference to this.
Further, from a OO perspective, you have to define a separate class, extending Horse and implementing KnowsHowToSwim. All instances of this are a Horse and know-how-swim. Of course you can create only one instance of it.
However you may define a class inside a method body (i.e. a factory method), a.k.a. local class. This class hold referece to all (effectively final) variables in the method. For example:
public static Horse newSwimmingHorse() {
final Object methodScopeProperty = ...;
class SwimmingHorse extends Horse implements KnowsHowToSwim {
double speed;
double getHowFast(){
methodScopeProperty.doSomething(); //do you need this access?
return speed;
}
}
return new SwimmingHorse();
}
But as long as you don't gain any benefits from the accessible method scope I wouldn't recommend it. Use a static inner class instead, optionally with limited visibility or a package-private class. This keeps your code more cohesive.
I have an abstract class called Car. Then I have two subclasses, Ford and Dodge which both extend Car. Each of these subclasses have a method called move(). The code in this method is identical for Ford and Dodge, so naturally my instinct was to throw this method implementation into the Car superclass so I don't have to have the same code twice in both my subclasses, i.e. get duplicated code, and just have this method written out once in code inside the superclass, and each subclass can call it when it needs to.
Now here's my...thing: Inside the move methods in each subclass, instance variables from each subclass are being manipulated. So you see, even though the code is identical, what is happening in each move()-method is depending on the state of that specific subclass's instance variables. Like this:
abstract class Car {
// I want to put move()-method in here and erase it from subclasses
}
class Ford extends Car {
private int rpm;
public void move(){
dosomestuff + rpm // value of rpm being used here is unique to Ford
}
}
class Dodge extends Car {
private int rpm;
public void move(){
dosomestuff + rpm // value of rpm being used here is unique to Dodge
}
}
I want to have it like this, and call move() in the superclass from each subclass using the subclasses instance variables:
abstract class Car {
move(){
// do stuff that is identical to Ford and Dodge but
// dependent on different instance variables
}
}
class Ford extends Car {
private int rpm;
}
class Dodge extends Car {
private int rpm;
}
Should I create variables inside the superclass Car? But that is what I am having problem wrapping my head around, because I know an abstract class cannot be instantiated! So if I were to pass the rpm-variable in this case as a parameter in the move() method like move(rpm), while I am having the implementation for move() only inside the Car class, I would have to return the rpm-variable to get its manipulated value back. This works, for once instance variable form a subclass. The problem is, the move-methods depend on several different kinds of variables. So I would have to return several variables back to the subclass each time but I am not sure how to do that.
I am confused. How can I condense this "duplicated code" inside my subclasses into the superclass Car and still be able to manipulate instance variables from the different subclasses inheriting from the Car class? Do I pass them as parameters and return them? Do I do something with get-set methods? I am so unsure...
Use protected variables
abstract class Car {
protected int rpm;
move(){
// ACCESS RPM HERE, which would be specific to implementing class
}
}
class Ford extends Car {
}
class Dodge extends Car {
}
Since the variable rpm is now protected, it will be accessible to the sub-classes of Car and when you instantiate Ford or Dodge, it would have it's own rpm value.
Makes sense?
I do not know if this answers your questions but sub classes inherit the methods of super classes so I would put everything in the abstract class and use getter setter (or access-mutate) methods to use all the variables in the abstract class. I notice someone has stated protected variables which will work sometimes but not if you need encapsulation within your package. I would do this:
public abstract class Car{
private int rpm;
public int getRPM(){return rpm;}
public void move(){//do move using getRPM() to access the data}
}
class Ford extends Car {
}
class Dodge extends Car {
}
So then the only thing different between Ford and Doge will be the constructor which is often times good when you are subclassing
As others have written, you can pull your instance variables into your base class; and make them either protected; or provide getters for them; but honestly, I think that most likely will lead to a bad design.
The thing is: inheritance should be used to provide behavior to its subclasses, not variables.
Meaning: you consider carefully what kind of behavior you want to "share"; and then you think about the open closed principle to implement it the right way, like:
abstract class Base {
public final void doTheCommonThing() {
System.out.println("but we need subclass stuff: " + getFromSubclass());
}
protected abstract String getFromSubclass();
}
The whole point of data encapsulation is that your base class should not know about variables in child classes; and vice versa. Because those are implementation details that nobody else has a business knowing about.
I am new to Java and I have read threads (here) that it is not possible to instantiate an abstract class. So, I tested it out.
The first test I did is shown below. And it seems like I can actually instantiate an abstract class and in fact, I actually have a new type which refers to the abstract class and the type is actually shared by all subclasses the extends it. This also means polymorhpism applies.
import java.util.*;
abstract class AbstractClass{
public abstract void printname();
}
class Test1 extends AbstractClass{
private String name;
public Test1(String name){
this.name = name;
}
public void printname(){
System.out.println("My name is " + name);
}
}
class Test2 extends AbstractClass{
private String saysomething;
public Test2(String saysomething){
this.saysomething = saysomething;
}
public void printname(){
System.out.println(saysomething);
}
}
class TestingApp{
public static void main(String[] args){
AbstractClass[] abstractclass_list = {new Test1("JEFFFFFF") , new Test2("Hey , say something")};
for(AbstractClass item : abstractclass_list){
item.printname();
}
}
}
Then I did another test but this time, instead of working on abstract class, I decided to create a type which refers to Interface. It seems like I can instantiate an interface as well. I can actually create a type that refers to the interface. This type is shared by all the classes that implements this interface. And polymorphism applies again.
import java.util.*;
interface AbstractInterface{
public void printname();
}
class Test4 implements AbstractInterface{
private String name;
public Test4(String name){
this.name = name;
}
public void printname(){
System.out.println("My name is " + name);
}
}
class Test3 implements AbstractInterface{
private String saysomething;
public Test3(String saysomething){
this.saysomething = saysomething;
}
public void printname(){
System.out.println(saysomething);
}
}
class TestingAbstractInterfaceApp{
public static void main(String[] args){
AbstractInterface[] abstract_list = {new Test4("Helen") , new Test3("Hey , say my name")};
for(AbstractInterface item : abstract_list){
item.printname();
}
}
}
Question:
I am sensing there is something wrong with what I am doing in my code. But I cannot quite explain how come the code still works when theoretically, it is impossible to instantiate an abstract class and interface. Am I actually instantiating an abstract class and an interface in the examples shown above ? Because this seems like exactly what I have done, as I have a new type for the abstract class and interface. Please correct me, if my logic is wrong or if I am using the wrong words.
Update:
SO I guess my misunderstanding is about type. I always thought type can only refer to normal Java classes but not abstract classes and interfaces. How does "type" actually work? Is it creating a reference?
Why do you think you are actually instantiating AbstractClass and AbstractInterface?
new Test1("JEFFFFFF") , new Test2("Hey , say something"), new Test4("Helen") , new Test3("Hey , say my name") are all instantiating concrete classes, not abstract ones.
If you refer to AbstractClass[] abstractclass_list = as proof of instantiating abstract classes, that is wrong. Here, you declare an array whose elements are of type AbstractClass, and Test1 and Test2 are (since they extend AbstractClass).
UPDATE
You could have something like this AbstractClass abs = new Test1("hey"); and what it does is it creates a new instance of class Test1, and references that instance from variable abs. abs's concrete type is Test1, but only methods declared in AbstractClass are visible on it. If you want to call methods of Test1, you would have to cast it first.
AbstractClass abs = new Test1("hey");
abs.printname(); // this is ok, and it calls `printname() implemented in Test1
abs.someTest1Method(); // this is NOT ok, someTest1Method() is not visible to abs
((Test1)abs).someTest1Method(); // this is ok, abs is cast to Test1, but would fail if abs was instantiated as 'abs = new Test2("t2")' (would throw ClassCastException)
You are not instantiating your abstract class or your interface. You are instantiating concrete classes that extend your abstract class (Test1 and Test2) or implement your interface (Test3 and Test4).
It's allowed to assign an instance of a concrete class to a variable whose type is an interface or an abstract class. In fact, it's even encouraged.
You aren't instantiating either an abstract class, nor an interface. You are just using the inherent upcasting ability from subclasses to superclasses.
Ignoring the array, and using just the first object, this would be equivalent to the implicit upcasts:
AbstractClass myObject = new Test1("JEFFFFFF");
and
AbstractInterface myObject = new Test1("JEFFFFFF");
So, in the code:
AbstractClass[] abstractclass_list = {
new Test1("JEFFFFFF") ,
new Test2("Hey , say something")};
You are instantiating objects of the concrete classes Test1 and Test2 - the Array contains references to the underlying (and common) abstract base class.
Similarly, in the second example, you are obtaining an array of interface references.
In short I would like to say that,
Parent(here, Abstract/Iterface) can refer, it's child(here, concrete class).
So here, reference variable can refer it's child class's instance.
Just note this concept in your brain, it will fix all your problem regarding, Dynamic Dispatcher, Inheritance related....!!!
You are not instantiating an abstract class and an interface,
you are instantiating some specific implementations of that abstract class and of that interface.
If you declare a list of AbstractClass or AbstractInterface you can just calls methods declared on your superclass or interface but not these declared on your specific implementations (Test1, Test2, Test3 and Test4).
I'm having a bunch of classes that I can not change; all these classes have a common ancestor (other than Object) that declares and implements the majority of their properties and methods.
Let's say, we have an inheritance tree like this (for illustration only):
class Vehicle
class Bicycle extends Vehicle
class Skateboard extends Vehicle
class Boat extends Vehicle
class Car extends Vehicle
class Aircraft extends Vehicle
class Jetplane extends Aircraft
class Helicopter extends Aircraft
...
class Truck extends Vehicle
...
While class Vehicle is actually more like an abstract class (it is not really, but it is never instantiated on its own behalf), objects of class Aircraft are created occasionally.
Now the point: the objects can have interrelationships that are not reflected by the classes. Since it is quite a bouquet of classes and the collection is subject to change every once in a while, it is not practical to maintain a subclass for each of the classes that implement the missing behavior.
My approach is therefore to have one class that serves as a wrapper for the above classes.
The constructor takes as a parameter the class of the respective object, which is then instantiated using reflection.
class VehicleW
{
// fields
public boolean isInitialized=false;
private Vehicle fVehicle;
...
// constructors
public VehicleW(Class aClass, ...)
{
Class VehicleClass = Vehicle.class;
if (!VehicleClass.isAssignableFrom(aClass))
return;
// <the reflection magic here>
...
// and on success mark this object as usable
isInitialized=true;
}
}
A constructor without arguments doesn't really make sense here. But now class Aircraft and its subclasses want some extra properties, so I thought I could establish a class AircraftW extends VehicleW that takes care of them.
The modification then looks like this:
// fields
private Aircraft fAircraft;
// constructors
public AircraftW(Class aClass, ...)
{
Class AircraftClass = AirCraft.class;
if (!AircraftClass.isAssignableFrom(aClass))
return;
// <the reflection magic here>
...
// and on success mark this object as usable
isInitialized=true;
}
But this fails, because Java intelligently inserts a call to the parameterless constructor of the ancestor, which is not present (and doesn't make sense, as already said).
It also doesn't make sense to call the parameterized super(), because I initialize a field of class Vehicle then. Okay, I can later in my AircraftW() just set that field to null, but that doesn't seem right.
Is there a way around this? Or am I taking an absolutely wrong approach? I thought about generics, but I can't seem to find a point using it. Interfaces? I'm not that much of a Java expert, so any recommendations are welcome.
Edit (not unsolved (to avoid the term solved)) Well, below you find a working program. I can't put it down as an answer, because Thomas led me to this code... with his answer... which I accepted as the solution... I can't see what's wrong with that.
Thanks, Thomas, for pointing me in the right direction.
For the sceptical, here the complete source code of a test program:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Vehicle { public Vehicle(){} }
class Bicycle extends Vehicle { public Bicycle(){} }
class Skateboard extends Vehicle { public Skateboard(){} }
class Boat extends Vehicle { public Boat(){} }
class Car extends Vehicle { public Car(){} }
class Aircraft extends Vehicle { public Aircraft(){} }
class Jetplane extends Aircraft { public Jetplane(){} }
class Helicopter extends Aircraft { public Helicopter(){} }
class Truck extends Vehicle { public Truck(){} }
class VehicleW
{
protected Vehicle fVehicle=null;
public boolean isInitialized=false;
public VehicleW(Class aClass)
{
if (checkVehicle(aClass))
if ((fVehicle=makeVehicle(aClass))!=null)
isInitialized=true;
}
protected boolean checkVehicle(Class aClass)
{
Class tClass = Vehicle.class;
return (tClass.isAssignableFrom(aClass));
}
protected Vehicle makeVehicle(Class aClass)
{
Vehicle tVehicle = null;
System.out.format("trying to create %s\n",aClass.toString());
Constructor c;
try
{
c=aClass.getConstructor();
}
catch(NoSuchMethodException e)
{
System.out.format(" no constructor found\n");
return null;
}
try
{
tVehicle=(Vehicle)c.newInstance();
}
catch(InvocationTargetException e)
{
System.out.println(e.toString());
}
catch(InstantiationException e)
{
System.out.println(e.toString());
}
catch(IllegalAccessException e)
{
System.out.println(e.toString());
}
return tVehicle;
}
public Vehicle getVehicle()
{
if (!isInitialized)
return null;
return fVehicle;
}
public Class getWClass()
{
if (!isInitialized)
return null;
return fVehicle.getClass();
}
}
class AircraftW extends VehicleW
{
public AircraftW(Class aClass)
{
super(aClass);
/*
Class tClass=Aircraft.class;
if (!tClass.isAssignableFrom(aClass))
return;
isInitialized=true;
*/
}
#Override
protected boolean checkVehicle(Class aClass)
{
Class tClass = Aircraft.class;
return (tClass.isAssignableFrom(aClass));
}
}
class program
{
public static void tellme(VehicleW vx)
{
String s = "failed";
if (vx.getVehicle()!=null)
s="succeeded";
System.out.format(" making %s for %s %s\n",
vx.getWClass(),vx.getClass(),s);
}
public static void main(String[] args)
{
VehicleW v1, v2, v3;
AircraftW a1, a2, a3;
v1=new VehicleW(Bicycle.class);
tellme(v1);
v2=new VehicleW(Boat.class);
tellme(v2);
v3=new VehicleW(Helicopter.class);
tellme(v3);
a1=new AircraftW(Helicopter.class);
tellme(a1);
a2=new AircraftW(Aircraft.class);
tellme(a2);
a3=new AircraftW(Truck.class);
tellme(a3);
return;
}
}
and the output:
trying to create class Bicycle
making class Bicycle for class VehicleW succeeded
trying to create class Boat
making class Boat for class VehicleW succeeded
trying to create class Helicopter
making class Helicopter for class VehicleW succeeded
trying to create class Helicopter
making class Helicopter for class AircraftW succeeded
trying to create class Aircraft
making class Aircraft for class AircraftW succeeded
making null for class AircraftW failed
This sounds a lot like the factory pattern so you might want to look into that.
What you basically would do is something like this:
class VehicleFactory {
public static Vehicle createAircraft( /*Aircraft specific parameters*/) {
//build and return Aircraft, you can call your reflection magic here
}
public static Vehicle createBoat( /*Boatspecific parameters*/) {
//build and return Boat, you can call your reflection magic here
}
}
Additionally, you might want to look into the builder pattern.
In your approach there are several issues:
Prematurely returning from a constructor would still kept the created object, it might just not be properly initialized (you're using an attribute to signal full initialization but what do you do with uninitialized objects besides removing them? In that case initialized should not be a property of the objects or wrappers themselves).
If you have such a high number of subclasses you might want to check what the differences are. It might be a more flexible approach to use composition instead of inheritance.
Example of the last point:
class Vehicle {
VehicleType type; //e.g. Aircraft, Boat, Car
Set<Features> features; //e.g. 2 wheels, 4 wheels, wings etc.
Behavior behavior; //Class to implement specific behavior, depending on your needs
}
class AircraftBehavior extends Behavior {
void fly() {
//implements flying mechanic
}
//method overridden/implemented from Behavior
#Override
void move() {
fly();
}
}
//create an aircraft
Vehicle aircraft = new Vehicle( VehicleType.AIRCRAFT, new HashSet<Feature>(new WingsFeature()), new AircraftBehavior());
The last part would also be predestined for using the factor or builder pattern.
When child class can not full fill the contract of constructor with parent class. Then at same place exists a design defect.
The issue/reason can be that the child class is not valid as a child class or the parent class has to many functionalities.
For your example is really hard to tell what is breaking the contract. But the best and most flexible thing to work with are interfaces.
You claim that you are not an expert in Java. Interfaces are just a concept in Object Oriented programming in case you look for any carrier in this area you should be familiar with them. SO this might the time for you to learn more about interfaces and software design.
I am trying to understand better oop ,but I don't understand how to use abstract classes.
I have a car class, and a car can be mercedes , audi and volvo. Mercedes cars can have 5 passengers ,can open door and block windows; audi car can have 6 passengers, and just can open door. Volvo car can only have 3 passengers.
So, in order to do this, I created an interface:
public interface Car{
void openDoor();
void blockWindows();
int passengers=0;
}
then for each car I created an abstract class:
public abstract class Mercedes implements Car{
public void openDoor(){
System.out.println("Mercedes opendoor");
}
public void blockWindow(){
System.out.println("Mercedes blockwindow");
}
public Mercedes()
{
int passengers=5;
}
public abstract class Audi implements Car{
public void openDoor(){
System.out.println("Audi opendoor");
}
public Audi()
{
int passengers=6;
}
}
public abstract class Volvo implements Car{
public Volvo()
{
int passengers=6;
}
Now, I need to create an object that can transport maximum 15 cars. So I wrote:
public class TransportCars{
Car[] transport=new Car[15];}
//now I need to put in transport array differents types of cars. But I can not instantiate abstract classes. Should I use anything else? I used abstract classes because I can implement an interface and use just o part of it
Basically your design is completely wrong, as you are yet new to java, you first need to understand basic.
Design should be like this :
Car is a Vehical, so is-a relationship.
So you can create a Class Vehicle.
class Vehicle {
// properties of Vehicle like type of Vehicle, numberOfWheels etc.
String vType;
int numberOfWheels;
int passengers;
}
// Car is a Vehicle so it should extend Vehicle
class Car extends Vehicle {
String type; // sedan or hatchback
String manufacturer; // Mercedes, BMW, Audi, Volvo etc.
}
If you want to restrict Vehicle not to be instantiated, you can declare it as an abstract class
Interfaces and abstract classes have some similarities, but are not the same. For your example, you should probably make Car an abstract and have Mercedes, Audi, and Volvo extend that abstract class. Then make sure to implement any abstract methods in Car in each of your classes which extend it. Doing so will make them concrete classes, which can be instantiated.
One thing you can do with abstract classes which you cannot with interfaces, is include data. I see you're already doing that with your interface for number of passengers, but in an interface, the value will be static and final.
I see the problem why it's hard for you to understant abstraction, it's because your example is wrong. The type of car must be a concrete class which inherits from an abstract class. The specificity of an abstract class is that you can't create one of it, you can only inherit it ,that benefits polymorphism. But the real benefits comes from abstract methods.
Instead of creating a Car interface ,create a Vehicle interface.
Since you don't know how many passengers each type of car can carry make Car an abstract
class. Every vehicle have to start and stop. And you know that a car must load the passengers first in order to start. In the end you can start all your vehicles regardless what type car is it , οr what type of vehicle.
interface Vehicle {
public start();
public stop();
}
abstract class Car implements Vehicle {
protected wheels = 4;
public start() {
loadPassengers();
// do extra stuff like
//closeDoors();
}
abstract public loadPassengers();
}
public class Volvo extends Car {
int passengers = 6;
public loadPassengers() {
doSomething(this.passengers);
}
}
public static void main() {
List<Car> cars = new ArrayList<Car>();
cars.add(new Volvo());
cars.add(new Mercedes());
for(Car car : cars) {
car.start();
}
}
In terms of relationships between classes, there's notmuch differences between abstract classes and interfaces: You can't instantiate any of them and they would be used as a template for objects depending on them. You can implement partially the methods of an abstract class however, but even if all of them are implemented still you can't instantiate a class defined as abstract. To be concise:
Interfaces:
Define methods.
A class can implement several interfaces.
Public visibility (or package, by default).
Can't be instantiated.
Abstract classes:
Define methods and may implement them.
A class can inherit from only one class (abstract or not).
User defined visibility.
Can't be instantiated.
If your cars are meant to implement several interfaces, use interfaces, but their scope will have to be public or package. If you just want to have an inheritance relation with one class, use abstract.
It seems that you are going about this the wrong way. It would be better for you to seek a tutorial, but I will try to clear up as much as I can for you:
The car class should be either an interface or an abstract class (or neither).
If it's an interface, than Mercedes, Audi and Volvo should implement it.
If that is the case, any method in "car" must be implemented in the others, so all of them must have "Open door" and "Block windows". you must choose for each of the implementing classes how it will implement it.
If it's an abstract class, you can have some of the methods implemented in "car" and they will work "as is" in Mercedes, Audi and Volvo (which will "extend" car), unless you re-define them in their respective classes. if you want to enforce their implementation in each of inheriting classes, you can define those methods to be abstract in "car", and not implement them in car at all.
If you want to implement all of the methods in car, you don't need it to be abstract at all. You could still re-define them as mentioned above.