I created method like this, where I have 2 inputs.
first is type (e.g. 'd', 'h')
second is value (e.g. "15", "0.5")
I created function to convert it to minutes like this:
public Float toMinutes(char type, String value) {
Float minutes = 0f;
switch (type) {
case 'd': {
minutes += Integer.parseInt(value) * 1440;
break;
}
case 'h': {
minutes += Float.parseFloat(value) * 60;
break;
}
case 'm': {
minutes += Integer.parseInt(value);
break;
}
default: {
return 0f;
}
}
return minutes;
}
I decided to refactor it, because those multiplication looks "ugly" for me. I found a better solution called TimeUnit.
public Long toMinutes(char type, String value) {
Long minutesCounted = 0l;
TimeUnit tu = TimeUnit.MINUTES;
switch (type) {
case 'd': {
minutesCounted += tu.convert(Long.parseLong(value), TimeUnit.DAYS);
break;
}
case 'h': {
minutesCounted += tu.convert(Long.parseLong(value), TimeUnit.HOURS);
break;
}
case 'm': {
minutesCounted += tu.convert(Long.parseLong(value), TimeUnit.MINUTES);
break;
}
default: {
return 0l;
}
}
return minutesCounted;
}
The problem is that this converter allow only long values, so now it works only on inputs like 15h and it will not work on inputs like 1,5h. Any ideas how to improve my solution to work with floating numbers?
Instead of using magic constants, you could use TimeUnit to figure out the conversion rate for 1 d, h, etc. to minutes like this
public float toMinutes(char type, String value) {
switch (type) {
case 'd':
return Integer.parseInt(value) * TimeUnit.DAYS.toMinutes(1);
case 'h':
return Float.parseFloat(value) * TimeUnit.HOURS.toMinutes(1);
case 'm':
return Integer.parseInt(value);
default:
return 0;
}
}
Related
I'm new to learning Java and was trying to understand OOP, but I can't seem to find anyone who has the same exact question. My question is, is it okay to use methods inside a constructor like the example here:
package ezrab.nl;
public class Calculations {
private int number;
private int multiplier;
private String operator = "";
public Calculations(int number, String operator, int multiplier) {
this.number = number;
this.operator = operator;
this.multiplier = multiplier;
switch (getOperator()) {
case "+":
System.out.println(getNumber() + getMultiplier());
break;
case "-":
System.out.println(getNumber() - getMultiplier());
break;
case "*":
System.out.println(getNumber() * getMultiplier());
break;
case "/":
System.out.println(getNumber() / getMultiplier());
break;
case "%":
System.out.println(getNumber() % getMultiplier());
break;
default:
System.out.println("Something went wrong.");
}
}
public int getNumber() {
return this.number;
}
public void setNumber(int number) {
this.number = number;
}
public int getMultiplier() {
return this.multiplier;
}
public void setMultiplier(int multiplier) {
this.multiplier = multiplier;
}
public String getOperator() {
return this.operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
}
So I'd like to know, is it allowed to use the methods I've created inside the constructor.
EDIT: I'd like to point out that the program is working. I just want to know if I followed the rules to OOP correctly.
Put behavior of object separately with creation:
public class Calculations {
private int number;
private int multiplier;
private String operator = "";
public Calculations(int number, String operator, int multiplier) {
this.number = number;
this.operator = operator;
this.multiplier = multiplier;
}
public int getNumber() {
return this.number;
}
public void setNumber(int number) {
this.number = number;
}
public int getMultiplier() {
return this.multiplier;
}
public void setMultiplier(int multiplier) {
this.multiplier = multiplier;
}
public String getOperator() {
return this.operator;
}
public void setOperator(String operator) {
this.operator = operator;
}
public void print() {
switch (getOperator()) {
case "+":
System.out.println(getNumber() + getMultiplier());
break;
case "-":
System.out.println(getNumber() - getMultiplier());
break;
case "*":
System.out.println(getNumber() * getMultiplier());
break;
case "/":
System.out.println(getNumber() / getMultiplier());
break;
case "%":
System.out.println(getNumber() % getMultiplier());
break;
default:
System.out.println("Something went wrong.");
}
}
}
is it allowed to use the methods I've created inside the constructor.
It's allowed but dangerous as you need to know if everything which should be set, has been set. It's better to use the value which was passed as a parameter.
However your switch should be in the constructor as you can change the operator or operand later. I would have a separate method for it.
NOTE: Having a field called multiplier is confusing as it's not a multiplier in most cases.
Yes it's allowed but better way is to separate the behavior and construction of object. Constructors are mainly used to set properties of the class.
To better code in OOP (Object Oriented Programming) this concept you are referring to is known as Encapsulation. You can generally code in the way you are saying to do it. However, down the line when the application gets bigger, it would make your life much easier if you follow established design patterns. Please review this link for the Encapsulation concept:
https://www.tutorialspoint.com/java/java_encapsulation.htm
I am making a card class, and need to set the face (The number on the card) to the numbers 1-13. However, on a card, a 1 is an ace, a 13 is a king, a 12 is a Queen, and an 11 is a jack. How do I also set the number 1, and 11-13 to a string such as ace, king, queen, or jack? Any help is appreciated!
public void setFace(int f)
{
if(f >= 1 && f <= 13)
face = f;
else
face = 1;
}
public int getFace()
{
return face;
}
I'm assuming you have field like
public int face;
I guess it will work if it's what you meant
public String getFace() {
switch (this.face) {
case 1:
face = "Ace";
break;
case 11:
face = "Jack";
break;
case 12:
face = "Queen";
break;
case 13:
face = "King";
break;
default:
return Integer.toString(face);
break;
}
}
What do you think about this code..?
public void setFace(int f) {
switch (f) {
case 1:
face = 1;
break;
case 11:
face = 1;
break;
case 12:
face = 1;
break;
case 13:
face = 1;
break;
default:
face = f;
break;
}
}
How about using enums?
public enum CardValue {
ACE(1), TWO(2), THREE(3), ..... KING(13);
private int value;
private CardValue(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public CardValue getValueFor(int x) {
// iterate through CardValue enum and return correct instance of the enum
}
}
I'm working on a card game app and i finished the basic stuff and now i'm trying to make it look professional.
the first thing I want to do is the effect of the distribution of cards,
i want to make a shuffle card effect.
when a card is given to a player, I want at least 500 milliseconds difference to the next card that will be distributed to him.
ideas?
this is a part from my code..
private void SetTheGame() {
SetShuffleSound();
for ( int i = 0; i < Imagename.length;i++) {
Imagename[i] = (ImageView) findViewById(WTF[i]);
CountCards();
Random = getRandom();
SwitchImages SwitchMe = new SwitchImages(myNewArray[Random]);
int first = SwitchMe.ChangeImages();
Imagename[i].setImageResource(myNewArray[Random]);
Imagename[i].setVisibility(View.VISIBLE);
CardsCount valueOfCard = new CardsCount(myNewArray[Random]);
int a = valueOfCard.WhatsMyValue();
String b = valueOfCard.TheFamily();
switch (i) {
case 0:
if (first != 0) {
Imagename[0].setImageResource(first);
}
FirstColumnComputer.add(a);
FirstColumnComputerFAMILY.add(b);
break;
case 1:
if (first != 0) {
Imagename[1].setImageResource(first);
}
SecondColumnComputer.add(a);
SecondColumnComputerFAMILY.add(b);
break;
case 2:
if (first != 0) {
Imagename[2].setImageResource(first);
}
ThirdColumnComputer.add(a);
ThirdColumnComputerFAMILY.add(b);
break;
case 3:
if (first != 0) {
Imagename[3].setImageResource(first);
}
FourColumnComputer.add(a);
FourColumnComputerFAMILY.add(b);
break;
case 4:
if (first != 0) {
Imagename[4].setImageResource(first);
}
FifthColumnComputer.add(a);
FifthColumnComputerFAMILY.add(b);
break;
case 5:
FirstColumnPlayer.add(a);
FirstColumnPlayerFAMILY.add(b);
break;
case 6:
SecondColumnPlayer.add(a);
SecondColumnPlayerFAMILY.add(b);
break;
case 7:
ThirdColumnPlayer.add(a);
ThirdColumnPlayerFAMILY.add(b);
break;
case 8:
FourColumnPlayer.add(a);
FourColumnPlayerFAMILY.add(b);
break;
case 9:
FifthColumnPlayer.add(a);
FifthColumnPlayerFAMILY.add(b);
break;
}
Cards.remove(Random);
// MakeTheCardPause();
}
SentTheLinkedList();
}
MakeTheCardPause() is the problem...
private void MakeTheCardPause() {
Thread Timer = new Thread()
{
public void run()
{
try{
sleep(1000);
}catch(InterruptedException e)
{
e.printStackTrace();
}finally
{
//do something...
}
}
};
Timer.start();
}
thanks!
Many ways you can do this. Thread.sleep(500) is the way was you suggested but it is not what I would recommend. Here are two alternatives
Message Handler
An example
Handler mHandler = new Handler(){
public void handleMessage(Message msg){
super.handleMessage(msg);
switch(msg.what){
case shuffle:
// Do something
break;
case doneShuffle:
//Do something
}
}
};
Asynch Tasks
Here is an example:
private class shuffleCards extends AsyncTask<Card, Integer, Long> {
protected Long doInBackground(Card card) {
//Do something
//shuffle deck
// Escape early if cancel() is called
if (isCancelled()) break;
}
return deck;
}
protected void onProgressUpdate(Integer... progress) {
//Number of shuffled cards??
}
protected void onPostExecute(Long result) {
//Show card
}
}
Remember this is just a background task to display results. Your main thread will be handling the actual card values and handing them over to the Asynch task.
Good Luck
What about this? You need to have the sleep in the working thread, your code above is creating a new thread and telling it to sleep, which has no noticeable effect to the user.
private void SetTheGame() {
SetShuffleSound();
for ( int i = 0; i < Imagename.length;i++) {
Imagename[i] = (ImageView) findViewById(WTF[i]);
CountCards();
Random = getRandom();
SwitchImages SwitchMe = new SwitchImages(myNewArray[Random]);
int first = SwitchMe.ChangeImages();
Imagename[i].setImageResource(myNewArray[Random]);
Imagename[i].setVisibility(View.VISIBLE);
CardsCount valueOfCard = new CardsCount(myNewArray[Random]);
int a = valueOfCard.WhatsMyValue();
String b = valueOfCard.TheFamily();
switch (i) {
case 0:
if (first != 0) {
Imagename[0].setImageResource(first);
}
FirstColumnComputer.add(a);
FirstColumnComputerFAMILY.add(b);
break;
case 1:
if (first != 0) {
Imagename[1].setImageResource(first);
}
SecondColumnComputer.add(a);
SecondColumnComputerFAMILY.add(b);
break;
case 2:
if (first != 0) {
Imagename[2].setImageResource(first);
}
ThirdColumnComputer.add(a);
ThirdColumnComputerFAMILY.add(b);
break;
case 3:
if (first != 0) {
Imagename[3].setImageResource(first);
}
FourColumnComputer.add(a);
FourColumnComputerFAMILY.add(b);
break;
case 4:
if (first != 0) {
Imagename[4].setImageResource(first);
}
FifthColumnComputer.add(a);
FifthColumnComputerFAMILY.add(b);
break;
case 5:
FirstColumnPlayer.add(a);
FirstColumnPlayerFAMILY.add(b);
break;
case 6:
SecondColumnPlayer.add(a);
SecondColumnPlayerFAMILY.add(b);
break;
case 7:
ThirdColumnPlayer.add(a);
ThirdColumnPlayerFAMILY.add(b);
break;
case 8:
FourColumnPlayer.add(a);
FourColumnPlayerFAMILY.add(b);
break;
case 9:
FifthColumnPlayer.add(a);
FifthColumnPlayerFAMILY.add(b);
break;
}
Cards.remove(Random);
long sleepMax = 1000L;
Random r = new Random();
long delay = (long) (r.nextDouble() * range);
Thread.sleep(delay);
}
SentTheLinkedList();
}
So I wrote a method today that incorporated the use of nested switch statements, and the code looked fairly clean and concise to me, but I was told that nested switch statements are not typically the best way to go as they can get confusing with the more switch statements that you add on. Here is a sample of what my code looked like:
EnumOne enumOne;
EnumTwo enumTwo = null;
EnumTwo enumThree = null;
switch (enumOne) {
case CASE_ONE:
switch (enumTwo){
case A: enumTwo = EnumTwo.B; break;
case C: enumTwo = EnumTwo.D; break;
default: break;
}
switch (enumThree) {
case AA: enumThree = EnumTwo.BB; break;
case CC: enumThree = EnumTwo.DD; break;
default: break;
}
break;
case CASE_TWO:
case CASE_THREE:
switch(EnumTwo) {
default: break;
}
switch (enumThree) {
case AA: enumThree = EnumTwo.XX; break;
case CC: enumThree = EnumTwo.YY; break;
default: break;
}
break;
default:
break;
}
So my question would be, essentially, what would be a suitable alternative to these switch statements?
As using a lot of switch becomes pretty hard to read.
And any time a new case arises then we have to modify code and add a CASE
we can consider using polymorphism in such cases
I am going to give a simple class just to let you understand.
Suppose a class earlier with switch case
class Test
{
Animal a;
public Test(Animal a)
{
this.a=a;
}
public moveThisAnimal()
{
switch(this.a)
{
case fish:
System.out.println("swim");
break;
case dog:
System.out.println("walk");
break;
case bird:
System.out.println("fly");
break;
}
}
}
now we replace these switch with our polymorphism logic
Interface Animal
{
String move();
}
Class Dog implements Animal
{
public String move()
{
return "walk";
}
}
Class Bird implements Animal
{
public String move()
{
return "fly";
}
}
Class Fish implements Animal
{
public String move()
{
return "swim";
}
}
now we have Test class without switch case
class Test
{
Animal a;
public Test(Animal a)
{
this.a=a;
}
public moveThisAnimal()
{
System.out.println(this.a.move()); // all switch case statements removed
}
}
and even if we have to add further cases we have to just add implementations no change here
See your complete code and see if It is possible to Do
I recommend you replace each nested switch statement with a call to a procedure which then executes the nested switch code.
Write something like this instead:
EnumOne enumOne;
EnumTwo enumTwo = null;
EnumTwo enumThree = null;
switch (enumOne)
{
case CASE_ONE:
nested_switch1();
case CASE_TWO:
case CASE_THREE:
nested_switch2();
break;
default:
break;
}
nested_switch1() {
switch (enumTwo)
{
case A:
enumTwo = EnumTwo.B;
break;
case C:
enumTwo = EnumTwo.D;
break;
default:
break;
}
switch (enumThree)
{
case AA:
enumTwo = EnumTwo.BB;
break;
case CC:
enumTwo = EnumTwo.DD;
break;
default:
break;
}
break;
}
nested_switch2() {
switch(EnumTwo)
{
default:
break;
}
switch (enumThree)
{
case AA:
enumTwo = EnumTwo.XX;
break;
case CC:
enumTwo = EnumTwo.YY;
break;
default:
break;
}
}
If you have integers X and Y and you need to switch on both, you can combine them in some unambiguous way and switch on the combination. For example, if y < 10:
switch (x*10+y)
{
case 0: // x == y == 0
case 1: // x ==0, y == 1
///
case 10: // x == 1, y == 0
case 11: // x == y == 1
//
}
public String sizeOfSupermarket() {
String size;
switch (this.numberOfProducts) {
case (this.numberOfProducts > 5000):
size = "Large";
break;
case (this.numberOfProducts > 2000 && this.numberOfProducts < 5000):
size = "Medium";
break;
case (this.numberOfProducts < 2000):
size = "Small";
break;
}
return size;
}
the above is wrong, how to write the compare statement in case statement?
You can use a derived value, in this case look at the number of thousands.
public String sizeOfSupermarket() {
switch (this.numberOfProducts/1000) {
case 0: case 1: return "Small";
case 2: case 3: case 4: return "Medium";
default: return "Large";
}
}
Note: you have a bug in your code such that if the numberOfProducts is exactly 2000 or 5000, it will return null (assuming it compiled)
You can't use expressions in case statements. The condition is evaluated by the switch statement, and the case statements check if the result matches.
To do what you are trying to do, you will have to use a series of if and else if statements:
if(this.numberOfProducts > 5000) {
size = "Large";
}
else if(this.numberOfProducts > 2000 && this.numberOfProducts < 5000) {
size = "Medium";
}
else {
size = "Small";
}
if (numberOfProducts >= 5000)
size = "Large";
else if (numberOfProducts >= 2000)
size = "Medium";
else
size = "Small";
You cannot use switch to test for boolean expressions. You need to use if.
You can use switch if you want to check if a variable has one certain value, i.e.:
public String sizeOfSupermarket() {
String size;
switch (this.numberOfProducts) {
case 5000:
size = "Large";
break;
case 2000:
size = "Medium";
break;
case 100):
size = "Small";
break;
}
return size;
}
Java 1.6 does not support a conditional switch statement, your best bet would be to use the if then else control structure
No way. By definition switch/case is based on enumerated types only (int, boolean, long, enum) in all C-like languages I know.
So you have to use if/else structure here:
public String sizeOfSupermarket() {
String size;
if (this.numberOfProducts > 5000) {
size = "Large";
} else if (this.numberOfProducts > 2000 && this.numberOfProducts < 5000) {
size = "Medium";
} else (this.numberOfProducts < 2000) {
size = "Small";
}
return size;
}