I'm new to Java programming, sorry if this is a dumb question.
I find it hard to word this question properly, but I have an assignment to create a aircraft class that can make aircraft land, takeoff etc. And need to test it using Testclass. When the new object are entered it automatically assigns a unique ID to the aircraft in the constructor.
I can do this using a instance method fine as it has a return value which is returned to to Testclass. The question wants me to do this in the constructor itself, however, the constructor never returns anything. So the variable never gets sent to the Testclass. I clearly am not understanding OOP properly. Even when I try to just use a getter method to get the ID created in the constructor it gives me the initialized variable before the the constructor has worked on this. This is the code I have so far and its completely wrong I know but if someone could point me in the right direction or tell me how to word this question better it would be a massive help.
// I need to enter 3 aircraft into the system in the testclass
public class Aircraft {
private int aircraftID;
private static int lastID;
private String airportcode;
private int ID = 100;
private int count;
public Aircraft(int a, int b, int c){
// Constructor
// Assign ID
this.ID = a;
lastID = ID;
ID++;
this.ID =b;
lastID = ID;
ID++;
}
}
OK, you want to create an Aircraft that has an automatically-assigned unique identifier, and can take off and land. That implies you need a field for tracking the identifier, a field for tracking whether it's in the air (or not), and methods for the take off and land operations. You also need a static field for generating the unique identifiers. (Note that this implementation isn't thread safe.)
private class Aircraft {
private static int staticId = 0;
private int uniqueId = 0;
private boolean onGround = true; // Aircraft start on the ground in this implementation
public Aircraft(){
this.uniqueId = staticId; // putting this line first makes uniqueId zero-indexed in effect
staticId++;
}
public void land(){
onGround = true;
}
public void takeoff(){
onGround = false;
}
public boolean isFlying(){
return !onGround; // If it's not on the ground, it's flying
}
public int getUniqueId(){
return uniqueId;
}
}
Unit tests checks all of the methods and expected functionality of the class in question:
import org.junit.Test;
import static org.junit.Assert.*;
import Aircraft;
class Testclass {
private final Aircraft aircraft = new Aircraft();
#Test
public void hasId(){
aircraft.getUniqueId() >= 0;
}
#Test
public void canLand(){
assertTrue(aircraft.land());
}
#Test
public void canTakeOff(){
assertTrue(aircraft.takeOff());
}
#Test
public void checkFlightOperationsAreTrackedCorrectly(){
aircraft.land();
assertFalse(aircraft.isFlying());
aircraft.takeOff();
assertTrue(aircraft.isFlying());
}
}
As pointed out a constructor does not return anything (the simplified version is that with new it returns an object instance). I am kinda guessing at what you are trying to acomplish, but I'll have a go anyways. It seems to me that you are trying to cram the construction of 3 objects into one constructor - which is why your constructor has 3 parameters. Also you are playing havoc with the IDs.
I have removed all the variables that I didnt quite understand, leaving only ID that increments with each instantiated Aircraft. The #Override is mainly just for show.
public class Aircraft {
private int aircraftID;
private static int lastID = 0;
#Override
public String toString(){
return "Aircraft_" + this.aircraftID;
}
public Aircraft() {
lastID++;
this.aircraftID = lastID;
}
}
I took the liberty and wrote the TestClass just to see if we have the same thing in mind. Again the printAircraft() method is for show.
public class TestClass {
private List<Aircraft> aircrafts;
public TestClass(){
aircrafts = new ArrayList<>();
}
public void addAircraft(Aircraft a){
aircrafts.add(a);
}
public void printAircraft(){
Iterator<Aircraft> it = aircrafts.iterator();
while(it.hasNext()){
System.out.println(it.next().toString());
}
}
}
and to test it, we create and instance of TestClass add 3 Aircraft instances and print out the contents
public static void main(String[] args) {
TestClass tc = new TestClass();
tc.addAircraft(new Aircraft());
tc.addAircraft(new Aircraft());
tc.addAircraft(new Aircraft());
tc.printAircraft();
}
This would be the case if you are to write the TestClass. If that is given, it would help to know what it looks like - maybe that would help us understand better.
I have two combo-boxes as below,
whenever i click done button, i get the values from combo-box and store it in a object like below,
public class comboValues{
private String label1ComboString;
private String label2ComboString;
public String setLabel1Combo(String val){
this.label1ComboString = val;
}
public String setLabel2Combo(String val){
this.label2ComboString = val;
}
public void getLabel1Combo(){
return this.label1ComboString;
}
public void getLabel2Combo(){
return this.label2ComboString;
}
}
in a controller class i use,
comboValues obj = new comboValues();
obj.setLabel1Combo(label1ComboBox.getSelectionModel().getSelectedItem());
obj.setLabel2Combo(label2ComboBox.getSelectionModel().getSelectedItem());
For a design with two combo box the code looks simple. My doubt is what if the number of combo-boxes increases? with the above approach code will have
lot of lines. What is the design to overcome this problem and how can i implement that to this scenario?
You can have an array or an ArrayList of ComboBoxes. This way you can reference an arbitrary number of boxes. Your class would change to something like this:
public class ComboValues {
private String[] comboStrings;
...
public void setComboLabel(String label, int comboNum) {
comboStrings[comboNum] = label;
}
public void getComboLabel(int comboNum) {
return comboStrings[comboNum];
}
public void getComboBoxCount() {
return comboStrings.length;
}
}
...
String[] labels = ...
for (int i = 0; i < obj.getComboBoxCount(); i++) {
obj.setComboLabel(labels[i], i);
}
I can see from your approach that you want to add more combo-boxs and against it you want to do less code in java to handle those all.
You have option of implementing Array List collection and store multiple combo boxes inside this. so every time you will not be needed to create new object and it will become dynamic.
Hope it will clear your doubt. If you have not cleared please comment.
So I've read about the pass-by-value nature of Java and I've tried to change my variable after passing it to a function by having the function return the variable again. I didn't succeed in that.
My code
public class Logic {
private int position;
public class Logic(){
position = 1;
}
public void appendPosition(){
position = calculatePosition(position);
}
}
This is the barebones code. I call this method from an instance of Logic which is instantiated in another class:
public class MainLogic {
ILogic L;
public MainLogic(ILogic L){
this.L = L;
}
public void start(){
L.appendPosition();
}
}
Through repeated debugging I find to my dismay that the position variable does not change at all. The position variable passed to calculatePosition changes fine, as expected. What am I missing? I've tried making the variable public and static.
calculatePosition
private int calculatePosition(int position){
position += 6;
if(snakeLocations[position]>0) {
position -= 6;
}
else if(ladderLocations[position]>0) {
position += 6;
}
return position;
}
private final int[] snakeLocations = new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations = new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
public class Logic {
private int position;
public Logic(){
position = 1;
}
//to get position.....................
public int getPosition(){
return this.position;
}
public void appendPosition(){
position = calculatePosition(position);
}
private int calculatePosition(int position){
position += 6;
if(snakeLocations[position]>0) {
position -= 6;
}
else if(ladderLocations[position]>0) {
position += 6;
}
return position;
}
private final int[] snakeLocations =
new int[] {0,0,0,0,0,0,0,0,0,9,0,0,0,13,0,0,0,0,0,19,0,0,0,0,0};
private final int[] ladderLocations =
new int[] {0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,15,0,0,0,0,20,0,0,0,0};
}
//next class
public class MainLogic {
Logic L;
public MainLogic(Logic L){
this.L = L;
}
public void start(){
L.appendPosition();
}
public static void main(String[] args) {
Logic L = new Logic();
MainLogic ml = new MainLogic(L);
System.out.println(ml.L.getPosition());
ml.start();
System.out.println(ml.L.getPosition());
}
}
Let's read your code.
// There is a logic class.
public class Logic {
// So Logic has a position. it starts with zero.
private int position;
// Logic also has an inner class, also called Logic.
public class Logic(){
position = 1;
// When a new Logic().Logic() is created, the instance
// variable of the parent instance gets set to one. WHAT?!?
}
// ... lots of code
}
So, It's a bit like that Yo Dawg! meme - I heard you like Logic, so we've put A logic instance into your Logic instance so you can Logic while your Logic.
You probably want a constructor.
// So this is Logic.
public class Logic {
private int position;
// When an Logic instance is created, position starts with 1.
public Logic(){
this.position = 1;
}
Ok. So we're not talking about Yo Dawg Memes.
So Let's talk pass by value.
Pass-by-value means classes are like very egotistic children: You can't play with their toys, unless they tell you so.
This is a good thingĀ® since this means only the owning instance is allowed to change their private state. Trust me, it prevents quite a bit of havoc.
One way to allow the outside world to actually change the state is by using query and mutator methods. Back in the day, we used to call them getter and setter, but that sounds too simple, so software architects will usually use the fancier term.
But... all of this doesn't really apply since calculatePosition() is defined at Logic. Oops.
Let's try this:
Renaming some instance variables
Be a bit verbose to help the debugger. baby steps.
(Also, dropping a few jokes to fish for upvotes).
public class Logic {
private int position = 1;
public void appendPosition(){
// When debugging strange stuff,
// keep each step simple.
// Is calculatePosition working as it should?
int newPosition = calculatePosition(this.position);
this.position = newPosition;
}
// Always use parameters as final. It's good karma.
// You don't NEED to declare them as final,
// but let's try to be EXTRA clear.
private int calculatePosition(final int targetPosition){
// Yes, make as much as you can immutable
// You'll save a ton of mental bandwidth.
final int localCopy = targetPosition +6;
if(snakeLocations[localCopy]>0) {
return (localCopy -6);
// Don't force the maintenance programmer to
// read all your stuff. Return often, return early.
// This isn't Cc++, where you need to
// actually free your reference/pointers,
// so there's no point enforcing a single return.
}
if(ladderLocations[localCopy]>0) {
return (localCopy+6);
}
return localCopy;
}
}
So... Did this worked as it should?
I found the answer. This is often my mistake in posting here. I try to strip down my code as much as possible to ease the work for you guys, but sometimes the problem lies outside of the scope of what I provide due to a lack of understanding, or oversight, on my part.
I was actually calling MainLogic from two levels above:
public mainFrame() {
initComponents();
logic = Factory.getMainLogic();
}
where
public static class Factory {
public MainLogic getMainLogic(){
PlayerLogic pL = new PlayerLogic();
ImageLogic iL = new ImageLogic();
DieLogic dL = new DieLogic();
MainLogic mainLogic = new MainLogic(pL,iL,dL);
return mainLogic;
}
}
I forgot I had accidentally put Factory as static. My sincerest apologies for wasting your time.
My teachers source code was published and i was confused when i saw this:
New local variables where instantiated from a static variable, the variable was then used in a method and passed as an argument to another method, to then set its new value to the same static variable that the copy was based on. Since the scope of a static variable will be accessible throughout the class, why not access the static variable directly from every method within that class?
Why do this:
public class Calculator {
private JTextField displayText;
public void actionPerformed(ActionEvent e) {
String input = displayText.getText();
if (something == right) {
for (int i = 0; i < 10; i++) {
enterNumber(input);
}
}
}
public void enterNumber(String input) {
displayText.setText(input);
}
}
If you can just:
public class Calculator {
private JTextField displayText;
public void actionPerformed(ActionEvent e) {
if (something == right) {
for (int i = 0; i < 10; i++) {
enterNumber();
}
}
}
public void enterNumber() {
String localVar = "Kitten";
displayText.setText(localVar);
}
}
In this exact example you are right, there is no point in having a parameter in your enter number method.
but when you begin to work on more complex programs you start to notice that you end up using the same functionality over and over again, in which you can have a method with parameters, such that you can perform the same action with slight variation.
also it is easier to read for other people if you have a method with parameters, since all you have to do is say, "ok i call the method and send it blank, it sets the value to whatever i sent it.", instead of saying "ok i call the method, now lets see what the method does."
if your code works then it is not bad code. but if it works and is easy to read then it is good code.
I'm still a relative newbie when it comes to Java, coming mainly from a C# background.
I was discussing the lack of 'out' parameters in Java methods with a colleague and how to work around this. He suggested creating a structure/class to hold the various parameters and passing it back.
Sometimes this feels 'wrong' to me - especially if I have a special method that I want to use to return a subset of parameters from a larger class.
So I wondered about using anonymous inline classes instead to achieve this. Code sample below.
Is this a sensible approach? Just wondering what the perceived wisdom is on this.
public class MyClass {
Patient myPatient = null;
// An interface to enable us to return these variables in a single call
public interface VitalStatsResponse { public void returnStats(int bloodPressure, int heartRate); }
public class Patient {
int bloodPressure = 100;
int heartRate = 280;
// Lots of other variables here
public void calculateVitalStats(VitalStatsResponse response)
{
response.returnStats((bloodPressure * 2), (heartRate / 10) ;
}
}
public void doWork()
{
// We want the patient's blood pressure and heart rate returned by a single method call, so use an anonymous inline class
myPatient.calculateVitalStats(new VitalStatsResponse() {
#Override
public void returnStats(int bloodPressure, int heartRate) {
// Handle returned variables here
}
});
}
}
I would go for the simple solution of creating a VitalStats object. If you need the VitalStatus of a patient, then VitalStats is a concept in your application that can be represented as an Object.
public class VitalStatus {
final int bloodPressure;
final int heartRate;
public VitalStats(int bloodPressure, int heartRate) {
this.bloodPressure = bloodPressure;
this.heartRate = heartRate;
}
}
public class Patient {
int bloodPressure = 100;
int heartRate = 280;
// Other variables
public VitalStatus getVitalStatus() {
return new VitalStats(bloodPressured * 2, heartRate / 2);
}
}
Out params is a procedural solution for return times. Java primarily fits the Object Oriented paradigm of programming and as such don't be afraid to make objects. This fits with the S in SOLID if your class is doing a lot of complex things see if you can break it down into smaller more manageable pieces.
I would also use "class to hold the parameters" over "inline anonymous inner class"
public class MyClass implements VitalStatsResponse{
Patient myPatient = null;
private ArrayList<VitalStatsResponse> response;
void MyClass(ArrayList<VitalStatsResponse> response) {
this.response = response;
}
public class Patient {
int bloodPressure = 100;
int heartRate = 280;
// Lots of other variables here
public void calculateVitalStats()
{
for(int i = 0; i < response.length; i++) {
// call returnStats method of every registered callback
response.get(i).returnStats((bloodPressure * 2), (heartRate / 10) ;
}
}
}
// any client can register/unregister callback via these methods
void registerResponse(VitalStatsResponse response) {
this.response.add(response);
}
void unRegisterResponse(VitalStatsResponse response) {
this.response.remove(response);
}
public void doWork()
{
// We want the patient's blood pressure and heart rate returned by a single method call, so use an anonymous inline class
myPatient.calculateVitalStats();
}
public void returnStats(int bloodPressure, int heartRate) {
// implement the body according to this class requirement
}
}