Here is a toy example of my conundrum:
public abstract class Car {
public Car(Seat[] seatsParam) { // Could be protected.
driverSeat = new DriverSeat();
seats = new ArrayList<Seat>();
seats.add(driverSeat);
seats.addAll(seatsParam);
}
private final List<Seat> seats;
private final DriverSeat driverSeat;
}
public class MyCar extends Car {
public MyCar() {
super(new Seat[]{new PassengerSeat()}); // Cannot assign to member.
}
public PassengerSeat getPassengerSeat() { // Would like this accessor.
return passengerSeat;
}
private final PassengerSeat passengerSeat;
}
Car has a list of Seat (the seat supertype), ideally initialized in the constructor. Every car has a DriverSeat. MyCar also has a PassengerSeat which I would like to access from the subtype, but also from the parent list (as a Seat).
Some things that I have shot down:
The code above: passengerSeat won't be initialized in the subclass. I could get the list in MyCar's constructor and downcast, but this is ugly.
Making passengerSeat static: it shouldn't be static since there could be many other MyCars with unique seats.
Have Car define an abstract getSubclassSeats() to which it adds driverSeat: this won't work in the constructor since passengerSeat won't have been initialized. I could make seats non-final and do it after the constructor but, again, ugly.
I want to say this is something I should be able to express in OO, define a variable and pass it to the parent to reference. But I cannot think of how to do it nicely. It's been awhile since I worked with C++, but is this what initialization lists solve? If so, does Java have an equivalent?
I've seen people with similar problems use thread-local variables and god knows what other awful tricks, luckily there's an easy solution:
public MyCar() {
this(new PassengerSeat());
}
private MyCar(PassengerSeat seat) {
super(new PassengerSeat[]{seat});
// Well do something with your seat now.
}
Related
I am a beginner Java programmer. I am trying to access two lists from the class Car in the class Traffic, so I can perform a while loop that would loop till the lists from the main class are empty
This is the code I have now, I tried extending Traffic from the class car, but that didn't work and I am stuck. How can I solve this?
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
public class Car{
static String name;
public Object waiting_cars;
Car(String n) {
name = n;
}
public static void main(String[] args) {
List<Car> waiting_cars = new ArrayList<Car>();
List<Car> after_light = new ArrayList<Car>();)
for(int i =0; waiting_cars.size()<= 99; i++){
Car carname = new Car(name);
waiting_cars.add(carname); //CarClass#4617c264
}
System.out.println(waiting_cars.size());
}
}
class Traffic{
void trafficLights(){
while(!waiting_cars.size().equals(0)){ //WHERE THE PROBLEM OCCURS
}
}
}
As a beginner in Java (and probably, OOP as well), a lot of the fundamentals of Java have not yet settled in. So, you came up with an inadequate modelling of the problem domain.
A key idea of OOP is that data isn't stored in some globally available variables, but as private information within some class instance. And if you need to know that data, you have to kindly ask the instance for the information (by calling a method where the information is returned). And if the class doesn't have such a method, then the information is considered private and only visible to the instance itself that owns the field.
Let's have a look at your code now (I took the freedom to indent your code consistently, something that your IDE or Java-enabled editor can do automatically):
public class Car{
This class should contain the properties and functions of a single car (at least that's what everybody will expect from its name).
static String name;
By using static, you declare that all cars share exactly one name. Having individual names for cars (e.g. from the license plates) would be more plausible: omit the static keyword.
public Object waiting_cars;
Hereby you declare every Car to have waiting_cars - quite surprising, what does that mean that one car has waiting cars? This information should not be kept in the Car class (see below). And you should declare the data type you want to use for waiting_cars, e.g. List<Car> instead of Object.
Car(String n) {
name = n;
}
This defines a constructor, allowing you to supply a name for the car, by e.g. calling new Car("XYZ-123");. If you changed the static String name; to omit the static keyword, the constructor would become absolutely valid.
public static void main(String[] args) {
List<Car> waiting_cars = new ArrayList<Car>();
List<Car> after_light = new ArrayList<Car>();)
for(int i =0; waiting_cars.size()<= 99; i++){
Car carname = new Car(name);
The line above is nonsense (and will no longer even compile if you removed the static keyword). As it stands now, it takes the value of the static field name, supplies that to the Car constructor, and this constructor stores it into the static field name, exactly where it came from. And the variable name carname is misleading, as it sounds like a string naming a Car instead of what it is, a Car. A more plausible line would be Car car = new Car("Car-" + i);, giving names like "Car-0", "Car-1" and so on to the cars.
waiting_cars.add(carname); //CarClass#4617c264
}
System.out.println(waiting_cars.size());
}
}
The problem you describe comes from your modelling. You want to deal with traffic lights, and a better modelling would associate the waiting cars and those that passed with one traffic light instead of making them part of a Car.
So, you could create a class TrafficLight with fields waitingCars and carsPassed. As cars can arrive at the traffic light, and pass the trafficLight, two methods come to mind: arrive(Car car) and passNextCar(). Something like
public class TrafficLight {
private List<Car> waitingCars = new ArrayList<>();
private List<Car> carsPassed = new ArrayList<>();
public void arrive(Car car) {
waitingCars.add(car);
}
public void passNextCar() {
if (!waitingCars.isEmpty()) {
Car car = waitingCars.get(0);
waitingCars.remove(0);
carsPassed.add(car);
}
}
}
Right now, waitingCars and carsPassed are private and invisible to the outside world. If some other class needs to know about the cars that are waiting at or have passed a given traffic light, this other class will ask the traffic light for that information, by calling a method like trafficLight.getNumberWaiting(). Of course, such a method has exist in the TrafficLight class first, e.g.
public int getNumberWaiting() {
return waitingCars.size();
}
I want to inherit specific instances from a superclass, not all of them.
For example:
public class Snake extends Reptile {
private boolean hasLegs = false;
public Snake(double[] legLength, double tailLength, String color, boolean hasScales, boolean hasLegs) {
super(legLength, tailLength, color, hasScales);
this.hasLegs = hasLegs;
}
I want to inherit all instance variables from the class Reptile except double[] legLength(as snakes doesn't have legs).
How can I do that without changing code in the Reptile class?
Thanks.
I think you are asking how to not have to pass all the parameters you don't need to the parent class. You can't do that, you need to pass them all, but that doesn't mean you have to expose them all in the child class:
public Snake(double tailLength, String color, boolean hasScales) {
super(null, tailLength, color, hasScales);
this.hasLegs = false;
}
You can't just get some variables from the parent - you get them all. You can set them to values that make sense for your subclass. That is the whole point!
I have an array of objects from one class that I made, which includes both objects of that type and objects that extend the first object. I want to access a variable that the extending object has that the first object does not, once I know that the object I am talking about is the extending one. A simplified example of this is shown below:
public class Parent {
public boolean isChild=false;
}
public class Child extends Parent {
public int i=5;
public Child() {
isChild=true;
}
}
public class main {
public static void main(String[] args) {
Parent x=new Child();
if (x.isChild) {
System.out.println(x.i); //this is what I want to do...
//... but I get an error because Parent doesn't have a variable called i.
}
}
}
So, is there any way for me to get around this? (I looked at making a protected static variable but that didn't seem to be what I wanted because I need multiple copies of it.)
Okay, as for how this is actually being used (which I incorrectly didn't include the first time) I am making my own computer programming language for fun. I have an ArrayList of objects that have been created, and allow users of this language to make their own objects as well as use ones that I have made with both java code and code in my language.
I make strings (aka child) in java and have them extend my wafl_object class (parent). This way they can be carried around in that ArrayList without me having to go around with a different array for every object I make. However, I want to accept a String as a parameter for a different class, and I cannot see its value because it is in an object array and I was treating it like an object. I have now fixed this problem by casting it as a String, once I know that it really is one, and then looking at its value. In this situation, it was easier to just cast it, but in others abstactness may have been more usefull.
Instead of testing the type of the object, use polymorphism:
public abstract class Parent {
public abstract int getValue();
}
public class Child extends Parent {
#Override
public int getValue() {
return 5;
}
}
public static void main(String[] args) {
Parent x = new Child();
System.out.println(x.getValue());
}
Just try something like :
if(x instanceof Child){
System.out.println(((Child)x).i);
}
First of all, isChild can be replaced by using instanceof instead: if (x instanceof Child). Afterwards, you can safely cast x to Child: Child childX = (Child)x. childX then gives you access to x.
Generally, checking for types is frowned upon. Normally you should design your functions such that they accept a type that is general enough to do everything they need to do without having to cast to deriving class types.
You don't need your isChild variable. You can use if (x instanceof Child). But in order to access i, you'll have to case x to Child.
In addition, don't access a member directly. Data members such as i should be private and you should access them by getters.
public class main {
public static void main(String[] args) {
Parent x=new Child();
if (x instanceof Child) {
System.out.println((Child)x.getI());
}
}
}
You can solve this with instanceof and a cast, as described in other answers, but in general it's better to use polymorphism, to define a method that subclasses can override. The exact way to do this will depend on the exact nature of your program, but here's one possibility, where I'm using Employee for Parent and HourlyEmployee for Child (constructors and other logic would need to be filled in):
public class Employee {
private String name;
public String getDescription() {
return name;
}
}
public class HourlyEmployee {
private int wage;
#Override
public String getDescription() {
return super.getDescription() + " [at $" + wage + " per hour]";
}
}
Then the class that uses an Employee wouldn't need to test whether it's an HourlyEmployee; it just calls getDescription, and the method either will or won't include the hourly wage in the result, depending on what class it is.
There's no reason to use parent or use child
public class main {
public static void main(String[] args) {
Parent x=new Child();
if (x.isChild) {
System.out.println(((Child)x).i); //this is what I want to do...
//... but I get an error because Parent doesn't have a variable called i.
}
}
}
First of all, previous answers are correct and around the same point. You MUST let the compiler know that the you want to use (x) as a child and not parent.
So, and sticking with your code sample, the answer is to modify the System.out statement to the following:
System.out.println(((Child)x).getValue());
For example:
public class App {
private Car car = new Car();
public static void main(String[] args) {
// TO DO
}
}
If not good, what's the solution? How would you rewrite this code?
In my opinion everything depends in the design of the application you are working on. For the example provided I think it is acceptable. But for other more definitive data types, I would prefer constructor initialization. Primarily because constructor overloading is possible.
I have always been taught that you declare above and initialize inside. It is more efficient to initialize things inside of the constructor because if you need to change it with a passed in parameter upon construction you are initializing and assigning when you could just initialize.
For Example:
public class TestClass{
//Declared but uninitialized
Object obj;
//Makes no difference but easier to read
public TestClass(){
this.obj = new Object();
}
//In this constructor however the object being passed in is what is initializing obj
//-so if you were to initialize it above and then change it down here you are writing
//-to the mem twice and it is less efficient.
public TestClass(Object arg){
this.obj = (Object)arg;
}
}
The caveat to this is that memory these days is REALLY cheap. The only real purpose to doing it this way (other than not wanting to look like a rookie) is to make it manageable by other people.
Initializing the object in the declaration might be done if the program will "always" need an instance of the object and the cost of creating the instance is not too great (time, resources). Then yes, this type of "Eager Initiliazation" might be desired.
However, this design does go against OO design in keeping classes loosely coupled and make for harder unit testing.
In the example:
public class App {
private Car car = new Car();
}
You are saying:
App will "Always" require a Car object.
Car will always be instantiated after App is instantiated. (This can be problematic if the instantiation of Car is expensive IE. it also has several objects that are created at instantiation, and say, it loads in data from remote call of some type)
Ideally you would only want to create the object when it might actually be needed. Or in a constructor (default or overloaded) to provide some flexibility.
public class App {
private Car car;
App() {
}
// overloaded constructor
App(Car car) {
this.car = car;
}
public void setCar(Car car) {
this.car = car;
}
public Car getCar() {
return car;
}
public static void main(String[] args) {
// default constructor, lightweight, no car initialization happening;
App ap1 = new App();
// Ok, now I want a car, and it should be red.
Car redCar = new Car("red");
ap1.setCar(redCar);
// Using overloaded constructor, now I can control aspects of "car"
Car blueCar = new Car("blue");
App ap2 = new App(blueCar);
}
}
If you want your code to be easier to test it's a bad practice. The reason why is that creating App will also create a Car whether you want it or not. Now, if Car has code that connects to a database, oops, now when you test App you need to have a database available you can connect to or your test will fail.
The solution is Dependency Injection aka Inversion of Control. You'd write it like this:
public class App {
private Car car;
public App(Car car) {
this.car = car;
}
public static void main(String[] args) {
// TO DO
}
}
Now creating App doesn't necessarily create a Car and they are coupled less.
Now, I'm being very pedantic here. I probably use your example all the time in my code. I'm just pointing out a downside. This isn't ALWAYS bad and isn't ALWAYS good.
private Car car = new Car();
This perfectly ok IMHO. A couple of reasons for not doing it:
Car.<init> requires arguments that are only available in App.init
App has many fields and others are need to be initialized in App.<init> and for consistency you want to keep them all together.
In any case, don't do the following:
private Car car = null;
Because every java developer knows that instance fields are initialized to null.
Apart from what tieTYT wrote, what's maybe worth considering is that if you instantiate all members in the constructor, it makes it more readable. Everything you need to know about a new object of the type can be learned by reading the constructor.
The perfect way to execute this code would be to create an Object of type App in the main method which would invoke the constructor for the Car class.So the code would go like this.
public class App
{
private Car car;
public static void main(String[] args)
{
App app=new App(); //
app.car. //Followed by the method or the member variable that you would like to
//access
}
}
Use an Init() method for all initialization.
public class App {
private Car car;
public App() {
this.car = null;
}
public void Init() {
this.car = new Car();
}
public void Shutdown() {
this.car = null;
}
public static void main(String[] args) {
App app = new App();
app.Init();
app.Shutdown();
app = null;
}
}
note that there is a difference in the meaning between:
public class App {
private Car car = new Car();
public static void main(String[] args) {
// TO DO
}
}
and
public class App {
private Car car;
public App(){
car = new Car();
}
}
If new Car() fails in the first, for example, then you'll definitely have a fun time debugging that. The second is much more readable and debuggable if necessary. If you think of fields as sort of the pieces for the blueprint for a class, then it makes little sense to initialized them in their declaration.
Since you have main here, this is probably your entry point, but for other classes, if you think of them as blueprints for objects, then the idea of constructors makes a lot of sense:
public class App{
private Car car;
public Car getCar(){
return car;
}
public void setCar(Car car){
this.car = car;
}
public App(Car car){
this.car = car;
}
}
This, i suppose, is the most common structure for oop classes.
I have the following classes
class Person {
private String name;
void getName(){...}}
class Student extends Person{
String class;
void getClass(){...}
}
class Teacher extends Person{
String experience;
void getExperience(){...}
}
This is just a simplified version of my actual schema. Initially I don't know the type of person that needs to be created, so the function that handles the creation of these objects takes the general Person object as a parameter.
void calculate(Person p){...}
Now I want to access the methods of the child classes using this parent class object. I also need to access parent class methods from time to time so I CANNOT MAKE IT ABSTRACT.
I guess I simplified too much in the above example, so here goes , this is the actual structure.
class Question {
// private attributes
:
private QuestionOption option;
// getters and setters for private attributes
:
public QuestionOption getOption(){...}
}
class QuestionOption{
....
}
class ChoiceQuestionOption extends QuestionOption{
private boolean allowMultiple;
public boolean getMultiple(){...}
}
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption().getMultiple())
{...}
}
}
The if statement says "cannot find getMultiple for QuestionOption." OuestionOption has many more child classes that have different types of methods that are not common among the children (getMultiple is not common among the children)
NOTE: Though this is possible, it is not at all recommended as it kind of destroys the reason for inheritance. The best way would be to restructure your application design so that there are NO parent to child dependencies. A parent should not ever need to know its children or their capabilities.
However.. you should be able to do it like:
void calculate(Person p) {
((Student)p).method();
}
a safe way would be:
void calculate(Person p) {
if(p instanceof Student) ((Student)p).method();
}
A parent class should not have knowledge of child classes. You can implement a method calculate() and override it in every subclass:
class Person {
String name;
void getName(){...}
void calculate();
}
and then
class Student extends Person{
String class;
void getClass(){...}
#Override
void calculate() {
// do something with a Student
}
}
and
class Teacher extends Person{
String experience;
void getExperience(){...}
#Override
void calculate() {
// do something with a Teacher
}
}
By the way. Your statement about abstract classes is confusing. You can call methods defined in an abstract class, but of course only of instances of subclasses.
In your example you can make Person abstract and the use getName() on instanced of Student and Teacher.
Many of the answers here are suggesting implementing variant types using "Classical Object-Oriented Decomposition". That is, anything which might be needed on one of the variants has to be declared at the base of the hierarchy. I submit that this is a type-safe, but often very bad, approach. You either end up exposing all internal properties of all the different variants (most of which are "invalid" for each particular variant) or you end up cluttering the API of the hierarchy with tons of procedural methods (which means you have to recompile every time a new procedure is dreamed up).
I hesitate to do this, but here is a shameless plug for a blog post I wrote that outlines about 8 ways to do variant types in Java. They all suck, because Java sucks at variant types. So far the only JVM language that gets it right is Scala.
http://jazzjuice.blogspot.com/2010/10/6-things-i-hate-about-java-or-scala-is.html
The Scala creators actually wrote a paper about three of the eight ways. If I can track it down, I'll update this answer with a link.
UPDATE: found it here.
Why don't you just write an empty method in Person and override it in the children classes? And call it, when it needs to be:
void caluculate(Person p){
p.dotheCalculate();
}
This would mean you have to have the same method in both children classes, but i don't see why this would be a problem at all.
I had the same situation and I found a way around with a bit of engineering as follows - -
You have to have your method in parent class without any parameter and use - -
Class<? extends Person> cl = this.getClass(); // inside parent class
Now, with 'cl' you can access all child class fields with their name and initialized values by using - -
cl.getDeclaredFields(); cl.getField("myfield"); // and many more
In this situation your 'this' pointer will reference your child class object if you are calling parent method through your child class object.
Another thing you might need to use is Object obj = cl.newInstance();
Let me know if still you got stucked somewhere.
class Car extends Vehicle {
protected int numberOfSeats = 1;
public int getNumberOfSeats() {
return this.numberOfSeats;
}
public void printNumberOfSeats() {
// return this.numberOfSeats;
System.out.println(numberOfSeats);
}
}
//Parent class
class Vehicle {
protected String licensePlate = null;
public void setLicensePlate(String license) {
this.licensePlate = license;
System.out.println(licensePlate);
}
public static void main(String []args) {
Vehicle c = new Vehicle();
c.setLicensePlate("LASKF12341");
//Used downcasting to call the child method from the parent class.
//Downcasting = It’s the casting from a superclass to a subclass.
Vehicle d = new Car();
((Car) d).printNumberOfSeats();
}
}
One possible solution can be
class Survey{
void renderSurvey(Question q) {
/*
Depending on the type of question (choice, dropdwn or other, I have to render
the question on the UI. The class that calls this doesnt have compile time
knowledge of the type of question that is going to be rendered. Each question
type has its own rendering function. If this is for choice , I need to access
its functions using q.
*/
if(q.getOption() instanceof ChoiceQuestionOption)
{
ChoiceQuestionOption choiceQuestion = (ChoiceQuestionOption)q.getOption();
boolean result = choiceQuestion.getMultiple();
//do something with result......
}
}
}