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();
}
Related
I have created a (generic) class Store, which I use to get 3 stores(smithy, jeweler and bookstore). The store is basically just an ArrayList, which holds different objects, that can be bought in each store. Now I want to limit the smithy to only hold weapons, the jeweler to only hold rings, etc.
I tried realizing that like this:
Store<Weapon> smithy = new Store<>();
Store<Ring> jeweler = new Store<>();
Store<Scroll> bookstore = new Store<>();
However do I get an error later on in the code, because the method only accepts the type(Object, Store<Object>) and not (Object,Store<Weapon>). But the Weapon class is a subclass of my Object class, so I don't understand why this is a problem.
My Store class:
public class Store <T extends Object>{
/...
}
My Object Class:
public class Object {
//Konstruktor
public Object() {
}
}
My Weapon class :
public class Weapon extends Object {
//Konstruktor
public Weapon () {
super();
};
The piece of code I get the problem in:
this.myPlayer.buy(this.smithy.getItemAt(itemNr), this.smithy);
The buy method:
public void buy(Object obj, Store<Object> store){
//...}
the error:
the method buy(Object,Store<Object>) in the type Player is not applicable for the arguments (Object, Store<Weapon>)
Since I have three different stores with each their own kind of Objects(Weapon, Ring, Scroll) I cannot just change the buy method to (Object, Store<Weapon>). And writing three methods for each store seems a bit much to me.
I appreciate your helping.
Hi Everyone I am beginner in java and came across a question like Can I use variables for creating objects and calling methods to reuse the code.
Tesla.java
public class Tesla extends Car {
#Override
public void buy(){
System.out.println("Tesla bought");
}
#Override
public void sell(){
System.out.println("Tesla Sold");
}
}
Ford.java
public class Ford extends Car {
#Override
public void buy(){
System.out.println("Ford bought");
}
#Override
public void sell(){
System.out.println("Ford Sold");
}
}
Car.java
public class Car {
public static void main(String[] args) {
String[][] arr = {{"Tesla, Buy"},{"Ford", "Sell"},{"Benz", "Sell"}};
Car car = new Tesla();
car.buy();
Car car = new Ford();
car.sell();
}
public void buy() {
System.out.println("Car bought");
}
public void sell() {
System.out.println("Car Sold");
}
}
Here instead of creating each object I just want to use one for loop and create respective object and respective method based on the array elements.
Logic like below.
public static void main(String[] args) {
String[][] arr = {{"Tesla, Buy"},{"Ford", "Sell"},{"Benz", "Sell"}};
for(int i = 0;i<arr.length-1;i++){
Car car = new arr[i][0]();
car.arr[i][1];
}
}
How to achieve above logic? Is this something achievable in Java? I searched in google couldn't find relevant questions or problems. Please help me. Thanks in advance.
Note:- I don't want a workaround I just want to know the if logic is achievable using any advanced java concepts I am unaware of.
If you want to instantiate objects of various subclasses according to string inputs, you have at least two options:
Reflection
Builder pattern
Reflection
As commented by Nikolaus, one route is to use Java’s reflection facility. This is the “magic” way, where you would find at runtime the name of the class matching your string input. For example, "Tesla" string would lead you to loading an object of type Class representing the Tesla class you wrote at compile time. You would call methods on that Class object to create an instance of your subclass. In other words, you are programmatically doing a roundabout replacement for the code new Tesla(…).
I do not recommend going the reflection route. This is not “normal” Java app programming. Reflection is usually done only in certain kinds of frameworks and in special rare circumstances.
Builder pattern
The other route more commonly used is the Builder pattern. You define another class called something like CarBuilder. You pass your text values into one or more methods of an object of this type CarBuilder. Those methods validate the inputs.
When done setting up the various pieces of input, you eventually call a method conventionally called build. That method produces and returns an object of type Car. That Car object is actually from a subclass, is actually a Tesla or Ford.
CarBuilder builder = new CarBuilder() ;
builder.setBrand( "Tesla" ) ;
builder.set… = … ;
…
Car car = builder.build() ; // Actually a `Tesla` subclass object.
Rather than create different classes (Tesla, Ford) that inherit from a superclass (Car), just pass in parameters to your Car class methods:
public class Car {
public void Buy(String brand) {
System.out.println(brand+" bought");
}
public void Sell(String brand) {
System.out.println(brand+" Sold");
}
}
I would also move the main method out to a separate Runner class. Its only responsibility would be to run the program and nothing else. That way you decouple the classes that implement your model (Car...) from the classes used to run the program.
Additionally, my example is a bit weak in the sense that I have to pass in the brand for each method. What you should do instead is introduce the notion of a constructor in your Car class and the notion of a class attribute. Your code then becomes
public Class Car{
private String brand;
public Car(String brand){
this.brand = brand;
}
public void Buy(String brand) {
System.out.println(brand+" bought");
}
public void Sell(String brand) {
System.out.println(brand+" Sold");
}
}
One last thing: methods typically don't start with a capital letter in Java so you should rename Buy and Sell to buy and sell.
Your second requirement is also to parameterize the action (buy or sell). You can apply the same principle i.e. have a generic method (doAction()) that will now take in 2 parameters: the car brand and the action you want to do. But IMHO that's pushing it too far and losing value.
So, I have a program where many objects of several different classes need to read some (many) variables from an object of 'class X', to give it a name. A quick and simple way of doing this would be to make a singleton, which wouldn't be X itself but a class it access to. I've done this, and later on it started feeling dirty, and many seem to agree, so I'd like to change my design for this. I haven't found any ideas to replace this pattern, though, just "don't do it" and "pass the data around." I'd like my data to be read-only, though. I haven't found mention of any other patterns.
The best I've got to share these read-only variables, which seems perfectly fine to me, is to have a class SharedVars for the data to share, but in the form of an inner class. It's inside Data, which is an outer class that is able to modify SharedVars, encapsulating what's meant to be read-only for the other classes. Basically, any class that wants to read these variables needs a Data.SharedVars object:
public class Data {
public static class SharedVars {
private int encapsulatedData;
public int getData() {
return encapsulatedData;
}
}
// no one should touch this but Data:
static private SharedVars sharedData;
Data() {
sharedData = new SharedVars();
}
public SharedVars getDataRef() {
return sharedData;
}
// here's where this class (and only this class, whenever it's told)
// modifies the encapsulated data:
void manipulateData() {
sharedData.encapsulatedData = 5;
}
}
One of the classes that depends on this would take this form:
public class Client {
// This class can't access the data directly
// so it'll use Data's getter:
Data.SharedVars vars;
public Client(Data.SharedVars vars) {
this.vars = vars;
// vars.encapsulatedData = 5; // is not allowed, since the field is private (which is what I want)
}
public void go() {
// the proper way to get its hand on the data:
int data = vars.getData();
System.out.println("The data is " + data);
}
}
Main is not needed in this example, but I'll leave it here anyway:
public class Main {
static Data dataControl;
static Client client;
public static void main(String[] args) {
dataControl = new Data();
client = new Client(dataControl.getDataRef());
dataControl.manipulateData();
client.go();
}
}
Is this proper? Or, what are the risks here? Notice I don't want the objects to copy them for themselves, since they'll be changing all the time, and I don't entirely like the idea of having a reference to the 'class X' I've mentioned before.
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.
}
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.