How to handle the Duplicated blocks - java

I ran sonarqube, but it informed me the error
"Duplicated blocks" in class Gold & Silver.
I modified many things, but it didn't solve the problem
Here is my source
Gold and Silver is extends Plan
Here is a Plan.Source
public abstract class Plan {
public abstract double getBasicRate();
public abstract int getBasicMinute();
public abstract double getAdditionalLineRate();
public abstract double getRatePerExcessMinute();
public abstract String getPlanName();}
Here is Gold.Source
public class Gold extends Plan {
private static final double BASIC_RATE = 49.95;
private static final int BASIC_MINUTE = 1000;
private static final double ADDITIONAL_LINE_RATE = 14.50;
private static final double RATE_PER_EXCESS_MINUTE = 0.45;
private static final String PLAN_NAME = "Gold";
public double getBasicRate() {
return BASIC_RATE;
}
public int getBasicMinute() {
return BASIC_MINUTE;
}
public double getAdditionalLineRate() {
return ADDITIONAL_LINE_RATE;
}
public double getRatePerExcessMinute() {
return RATE_PER_EXCESS_MINUTE;
}
public String getPlanName() {
return PLAN_NAME;
}
}
Here is a Silver.Source
public class Silver extends Plan {
private static final double BASIC_RATE = 29.95;
private static final int BASIC_MINUTE = 500;
private static final double ADDITIONAL_LINE_RATE = 21.50;
private static final double RATE_PER_EXCESS_MINUTE = 0.54;
private static final String PLAN_NAME = "Silver";
public double getBasicRate() {
return BASIC_RATE;
}
public int getBasicMinute() {
return BASIC_MINUTE;
}
public double getAdditionalLineRate() {
return ADDITIONAL_LINE_RATE;
}
public double getRatePerExcessMinute() {
return RATE_PER_EXCESS_MINUTE;
}
public String getPlanName() {
return PLAN_NAME;
}
}
please help me

The code in Gold and Silver is identical, except from the data being assigned to the variables. You could refactor to something like this to remove duplication:
public class Plan {
private final double BASIC_RATE;
private final int BASIC_MINUTE;
private final double ADDITIONAL_LINE_RATE;
private final double RATE_PER_EXCESS_MINUTE;
private final String PLAN_NAME;
public Plan(double BASIC_RATE, int BASIC_MINUTE,
double ADDITIONAL_LINE_RATE, double RATE_PER_EXCESS_MINUTE,
String PLAN_NAME) {
this.BASIC_RATE = BASIC_RATE;
this.BASIC_MINUTE = BASIC_MINUTE;
this.ADDITIONAL_LINE_RATE = ADDITIONAL_LINE_RATE;
this.RATE_PER_EXCESS_MINUTE = RATE_PER_EXCESS_MINUTE;
this.PLAN_NAME = PLAN_NAME;
}
public double getBasicRate() {
return BASIC_RATE;
}
public int getBasicMinute() {
return BASIC_MINUTE;
}
public double getAdditionalLineRate() {
return ADDITIONAL_LINE_RATE;
}
public double getRatePerExcessMinute() {
return RATE_PER_EXCESS_MINUTE;
}
public String getPlanName() {
return PLAN_NAME;
}
}
Then Gold would look something like this:
public class Gold extends Plan {
public Gold() {
super(49.95, 1000, 14.50, 0.45, "Gold");
}
}
What we have done here is take code that is shared by 2 classes and moved it up into its parent class. By calling the super constructor in Gold we assign the variables to the values required by this implementation of the super class Plan.
We've also removed the static from the class variables. This means that the variables will be related to an instance of the class rather than the class itself.
We do this so that the variables in Plan will be related to each instance of Plan. This means we can use them in both the extending classes without data being mixed between.
In a lot of cases you wouldn't usually use static unless you actively wanted a variable to be accessible without a class instance. You can read more about static here.

I had this issue recently. Although you already have an accepted solution (and it's been 4 years), I would like to share another way.
I prefer to keep these constants as I find it more readable. A (soooo) simple solution was to rename the constant names ;) (i.e - prefixing them with SILVER_ or GOLD_).
KISS principle and it worked perfectly.
public class Gold extends Plan {
private static final double GOLD_BASIC_RATE = 49.95;
private static final int GOLD_BASIC_MINUTE = 1000;
private static final double GOLD_ADDITIONAL_LINE_RATE = 14.50;
private static final double GOLD_RATE_PER_EXCESS_MINUTE = 0.45;
private static final String GOLD_PLAN_NAME = "Gold";
public double getBasicRate() {
return GOLD_BASIC_RATE;
}
public int getBasicMinute() {
return GOLD_BASIC_MINUTE;
}
public double getAdditionalLineRate() {
return GOLD_ADDITIONAL_LINE_RATE;
}
public double getRatePerExcessMinute() {
return GOLD_RATE_PER_EXCESS_MINUTE;
}
public String getPlanName() {
return GOLD_PLAN_NAME;
}

If you really want to have a separate Gold and Silver class like this you can't avoid the duplicate code blocks. You could suppress the Sonar violations, either by adding the following line above the line causing the violation (see Sonar FAQ):
// NOSONAR
Alternatively you could use an enum to represent these values:
public enum Plan {
GOLD(49.95, 1000, 14.50, 0.45, "Gold"),
SILVER(29.95, 500, 21.50, 0.54, "Silver");
private double basicRate;
private int basicMinute;
private double additionalLineRate;
private double ratePerExcessMinute;
private String planName;
private Plan(double basicRate, int basicMinute, double additionalLineRate, double ratePerExcessMinute, String planName) {
this.basicRate = basicRate;
this.basicMinute = basicMinute;
this.additionalLineRate = additionalLineRate;
this.ratePerExcessMinute = ratePerExcessMinute;
this.planName = planName;
}
public double getBasicRate() {
return basicRate;
}
public int getBasicMinute() {
return basicMinute;
}
public double getAdditionalLineRate() {
return additionalLineRate;
}
public double getRatePerExcessMinute() {
return ratePerExcessMinute;
}
public String getPlanName() {
return planName;
}
}
This also avoids duplicated blocks but might not suit your needs.

Related

Java calling method in another class

I am trying to create a Java class with certain number of pizzas that decreases in number
if someone steals it.
I have two classes.
class House where pizza is,
public class House {
private static int totalPizzas;
public House() {
totalPizzas = totalPizzas;
}
public int getTotalPizzas() {
return totalPizzas;
}
public static void setTotalPizzas(int totalPizzas) {
totalPizzas = totalPizzas - Thief.stealPizza(House stolenPizza);
}
}
and class Thief that steals the pizza.
public class Thief {
private String name;
private int age;
public Thief() {
name = "abc";
age = 11;
}
public static void stealPizza(House stolenPizza) {
???????
}
}
My main concern is the ??????? part where I feel like I should set stolenPizza to certain
integers but
stolenPizza = 1;
certainly does not work.
Could someone give me a bit of advice on how I should approach this?
Thank you very much for reading.
One way to do it would be to do something like:
public class Thief {
private String name;
private int age;
public Thief() {
name = "abc";
age = 11;
}
public static void stealPizza() {
House.setTotalPizzas(House.totalPizzas - 1);
}
}
public class House {
private static int totalPizzas;
public House() {
totalPizzas = totalPizzas;
}
public int getTotalPizzas() {
return totalPizzas;
}
public static void setTotalPizzas(int totalPizzas) {
House.totalPizzas = totalPizzas;
}
}
Your constructor is missing something if I understand your code right:
Your code
public House() {
totalPizzas = totalPizzas;
}
will set the amount of totalPizzas on itself without assigning any "real" integer value to it. Try
public House(int totalPizzas) {
totalPizzas = totalPizzas;
}
so that you actually can assign a number of Pizzas to the house when calling the constructor, for example:
House house = new House (12);
if you want to have 12 Pizzas in the house.

Java (for Android) Define and Initialize class array inside class array (c-like struct)

I am rewriting c code to Java to run on an Android-based BeagleBone Black. Since there are not struc types in java, I'm defining the data structures using public static class methods. However, in the structures are an array of sub-structures. As a model, say we want to define a class called Satellites. In each Satellite are Transponders and for each transponder is the channel information. I am trying to figure out how to declare and then initialize the sub-classes inside the class. My basic definition is:
public static final int SATELLITE_MAX = 50;
public static final int TRANSPONDER_MAX = 24;
public static final int CHANNEL_MAX = 36;
public static class satellite_struct {
public string satId;
public string satName;
public string satLocation;
public class transponder_struct {
public int frequency;
public char polarity;
public class channels_struct {
public string channel_name;
public string encryption;
public int sid;
}
}
}
I can instantiate the satellite structure class as follows:
satellite_struct satellites[] = new satellite_struct[SATELLITE_MAX]
but, how do I initialize the x transponders and y channels inside this class?
Thanks.
The "easiest" solution would be:
public static class satellite_struct {
public string satId;
public string satName;
public string satLocation;
public class transponder_struct {
public int frequency;
public char polarity;
public class channels_struct {
public string channel_name;
public string encryption;
public int sid;
}
public channels_struct[] channels = new channel_struct[ CHANNEL_MAX ];
}
public transponder_struct transponders = new transponder_struct[ TRANSPONDER_MAX ];
}
Given that you defined
satellite_struct satellites[] = new satellite_struct[SATELLITE_MAX];
You can then access them by (e.g.):
satellites[x].transponders[y].channels[z].channel_name
However, you'd probably want to Java-fy it a bit:
public static class Satellite {
public string satId;
public string satName;
public string satLocation;
public class Transponder {
public int frequency;
public char polarity;
public class Channel {
public string channel_name;
public string encryption;
public int sid;
}
public Channel[] channels = new Channel[ CHANNEL_MAX ];
}
public Transponder transponders = new Transponder[ TRANSPONDER_MAX ];
}
Class names are customarily upper-case in Java. If this is a direct translation to an existing structure, the above should do, but you might want to use a List or SparseArray instead of arrays.
Declare transponders here;
Declare channels here;
public static class satellite_struct {
public string satId;
public string satName;
public string satLocation;
public []transponder t;
public []channel c;
public satellite_struct(int x,int y)
{
//here
t=new transponder[x];
for(....)
t[i]=new transponder(params);
c=new channel[y];
for(....)
c[i]=new channel(params);
}
}
I got it to work as follows, and Java-ifying my syntax. The issue was with where to place the [] declaring an array of objects:
public static class Satellite {
public String satId;
public String satName;
public String satLocation;
public static class Transponder {
public int frequency;
public char polarity;
public static class Channel {
public String channel_name;
public String encryption;
public int sid;
}
public Channel channels[] = new Channel[CHANNELS_MAX];
}
public Transponder transponders[] = new Transponder[TRANSPONDERS_MAX];
}
Then, in my main code:
Structures.Satellite satellites[] = new Structures.Satellite[SATELLITES_MAX];
satellites[0].transponders[0].channels[0].channel_name="HELLO";
Update: It appears that while the IDE allows me to 'see' the transponders and channels when coding, when the code runs it returns error "all elements are null" for these sub-array values. How to initialize these?

Using enums in Java

Constants given in the following enum,
enum StringConstatns {
ONE {
#Override
public String toString() {
return "One";
}
},
TWO {
#Override
public String toString() {
return "Two";
}
}
}
public final class Main {
public static void main(String... args) {
System.out.println(StringConstatns.ONE + " : " + StringConstatns.TWO);
}
}
can be accessed just like StringConstatns.ONE and StringConstatns.TWO as shown in the main() method.
I have the following enum representing an int constant(s).
public enum IntegerConstants
{
MAX_PAGE_SIZE(50);
private final int value;
private IntegerConstants(int con) {
this.value = con;
}
public int getValue() {
return value;
}
}
This requires accessing the constant value like IntegerConstants.MAX_PAGE_SIZE.getValue().
Can this enum be modified somehow in a way that value can be accessed just like IntegerConstants.MAX_PAGE_SIZE as shown in the first case?
The answer is no, you cannot. You have to call:
IntegerConstants.MAX_PAGE_SIZE.getValue()
If you really want a shortcut, you could define a constant somewhere like this:
public class RealConstants {
final public static int MAX_PAGE_SIZE = 50;
}
public enum IntegerConstants
{
MAX_PAGE_SIZE(RealConstants.MAX_PAGE_SIZE);//reuse the constant
private final int value;
private IntegerConstants(int con) {
this.value = con;
}
public int getValue() {
return value;
}
}
This is not going to work because your first example does implicit calls to .toString() when you concatenate them with +, whereas there is no implicit conversion to int which is needed for your second example.
You could define them as static final fields, this does exactly what you are searching for:
public class IntegerConstants {
public static final int MAX_PAGE_SIZE = 50;
}

Private access errors

I'm having trouble with a problem I'm working on for class.
The errors occurring are
TC1.java:17: error: myQuantity has private access in CheckItem
items[i].myQuantity=quantities[i];
and
TC1.java:20: error: myPrice has private access in CheckItem
a[i]=items[i].myPrice*((items[i].mySalesTax\100)+1);
This is the code I currently have.
public class CheckItem
{
private double myPrice,
mySalesTax;
private int myQuantity = 1;
public CheckItem( double price, double salesTax )
{
myPrice = price;
mySalesTax = salesTax;
}
public int getQuantity()
{
return myQuantity;
}
public void setQuantity( int qty )
{
myQuantity = qty;
}
public double lineItemTotal()
{
return roundMoney((myPrice*myQuantity)*((mySalesTax/100)+1));
}
public static double roundMoney( double amount )
{
return (int)(100 * amount + 0.5) / 100.0;
}
public static void setQuantities( CheckItem[] items, int[] quantities )
{
for (int i=0;i<quantities.length;i++){
items[i].myQuantity=quantities[i];
}
}
public static double[] lineItemTotals( CheckItem[] items )
{
double[] a=new double[items.length];
for (int i=0;i<items.length;i++){
a[i]=items[i].myPrice*((items[i].mySalesTax/100)+1);
}
return a;
}
}
The problem is that static methods can't access private instance variables. Define getters and setters for those variables, and use them:
items[i].setQuantity(quantities[i]);
a[i]=items[i].getPrice()*((items[i].getSalesTax()\100)+1);
and it will work.
This code compiles fine. If you are trying to access private members outside this class you would get private access error during compilation. In that case standard fix is to provide setters and/or getters.
** EDIT **
Seems like there is confusion about allowed access. You can NOT access any instance variables from static methods/context DIRECTLY! But you CAN access instance variables via instance itself as shown here:
class Test {
private int s = 123;
void instPrint() {
System.out.println(s); // fine
}
static void statPrint(Test ss) {
System.out.println(ss.s); // this is fine too!
// System.out.println(s); // does not compile obviously
}
}
This is the same case as in the code above. This has nothing to do with access modifiers because it's all happening in the same class.
Your code declares these two member variables in class CheckItem with the private scope. This means no other classes can access them directly on a CheckItem instance:
private double myPrice,
mySalesTax;
If you want class TC1 to be able to read or modify them, declare them in CheckItem.java as public. Alternatively, and generally a better practice, you could add public methods to CheckItem.java to allow other classes to access their values:
public double getMyPrice() {
return this.myPrice;
}
public void setMyPrice(double price) {
this.myPrice = price;
}
public double getMySalesTax() {
return this.mySalesTax;
}
public void setMySalesTax(double st) {
this.mySalesTax = st;
}
public int getMyQuantity() {
return this.myQuantity;
}
public void setMyQuantity(int newQty) {
this.myQuantity = newQty;
}
Then, in TC1.java you'd use these methods instead of direct access:
items[i].setMyQuantity(quantities[i]);
and
a[i]=items[i].getMyPrice()*((items[i].getMySalesTax()\100)+1);

Is it the right way to do what Im trying? Abstract static variable?

Look on the code below. It seems to be like there is easier way to do it.
For each new Class I want to add to the system, I have to do the following in order to set the class variable(static -> maxPlayers)?
Something like Abstract static variable?
protected abstract class Class{
protected abstract int getMaxPlayers();
public class Soldier extends Class{
public static final int maxPlayers = 4;
#Override
protected int getMaxPlayers() {
return Soldier.maxPlayers;
}
}
public class Demoman extends Class{
public static final int maxPlayers = 2;
#Override
protected int getMaxPlayers() {
return Demoman.maxPlayers;
}
}
public class Scout extends Class{
public static final int maxPlayers = 4;
#Override
protected int getMaxPlayers() {
return Scout.maxPlayers;
}
}
public class Medic extends Class{
public static final int maxPlayers = 2;
#Override
protected int getMaxPlayers() {
return Medic.maxPlayers;
}
}
}
its just like i have to repeat this template:
public static final int maxPlayers = 2;
#Override
protected int getMaxPlayers() {
return Medic.maxPlayers;
}
And i think it is not correct to do so.
First of all, you shouldn't name your class Class (not even for examples). Choose a better name.
Secondly, it seems like an enum is what you really need here:
public enum Army {
SOLDIER(4),
DEMOMAN(2),
SCOUT(4),
MEDIC(2);
private final int maxPlayers;
private Army(int maxPlayers) {
this.maxPlayers = maxPlayers;
}
public int getMaxPlayers() {
return maxPlayers;
}
}
No, you can't have an static variable in a base class that has a different value for each subclass (as far as I can tell, this is what you'd ideally want to do).
The way you did it is one option, another is using a non-static variable, as below.
And your variable should preferably have less scope than your getter function.
class Class
{
private final int maxPlayers;
Class(int max)
{
maxPlayers = max;
}
public int getMaxPlayers()
{
return maxPlayers;
}
}
class Soldier extends Class
{
Soldier()
{
super(4);
}
}
To increase readability and modifiability, you may want to consider replacing 4 here with an enum or similar.
Another way:
abstract class Class
{
public static int MAX_PLAYERS_SOLDIER = 4,
MAX_PLAYERS_DEMOMAN = 2,
...;
protected abstract int getMaxPlayers();
}
class Soldier extends Class
{
#Override
protected int getMaxPlayers()
{
return MAX_PLAYERS_SOLDIER;
}
}

Categories

Resources