I got a simple question. I have a class, which I use for purpose of splitting a string in 2 years:
public class Period {
int firstYear;
int secondYear;
Period () {
}
Period(String periode) {
String [] periodeSplit = periode.split("-");
this.firstYear = Integer.parseInt(periodeSplit[0]);
this.secondYear = Integer.parseInt(periodeSplit[1]);
}
public String toString() {
return "Firstyear: " + this.firstYear + "\n" + "Secondyear: " + this.secondYear;
}
}
I now want to extend this class, not splitting the data into 2 different ints but into 3 different ints. So besides the 2 already exisiting integer vars I want one extra. Whats the easiest way of doing this?
Your help is appreciated!
Kind regards,
Kipt Scriddy
I think it would be better (and quite easy) the create more general class that will be able to deal with any number of years you pass to it:
public class Period {
int[] years;
Period() {
}
Period(String periode) {
String[] periodeSplit = periode.split("-");
years = new int[periodeSplit.length];
for (int i = 0; i < periodeSplit.length; i++) {
years[i] = Integer.parseInt(periodeSplit[i]);
}
}
public String toString() {
String result = "";
for (int i = 0; i < years.length; i++) {
result += "Year " + i + ":" + years[i] + "\n";
}
return result;
}
}
If the original class really have to be extended than it can be done like this:
class ExtendedPeriod extends Period {
int thirdPart;
ExtendedPeriod(String periode) {
String[] periodeSplit = periode.split("-");
this.firstYear = Integer.parseInt(periodeSplit[0]);
this.secondYear = Integer.parseInt(periodeSplit[1]);
this.thirdPart = Integer.parseInt(periodeSplit[1]);
}
public String toString() {
return "Day: " + this.firstYear + "\n" + "Month: " + this.secondYear
+ "\nYear: " + this.thirdPart;
}
}
I would recommand to change variable names 'firstYear' and 'secondYear' to something different, like 'firstPart', 'secondPart' because for extendedPeriod they aren't years anymore (I left them in my code so it would compile with yours but called the new int 'thirdPart'). I don't feel that this is the best use of inheritance but if that's what's needed. I also wanted to reuse toString from Period like this:
public String toString2() {
return super.toString() + "\nThird part: " + this.thirdPart;
}
but for it to have sense you would have to chagne toString method in Period not to call values 'years'.
When you extend the class, split it into two variables first, the one that's different from your current code, and then the one that your current code would handle.
Then simply call super(periode)
The child class will have access to the parent variables, since you made them default.
I wouldn't extend to just add a new year.
Why not make the entire thing generic enough, so that it supports whatever split you need.
public class Period {
String [] periodeSplit;
Period(String periode) {
periodeSplit = periode.split("-");
}
public String toString() {
//TODO : Iterate and print.
}
}
Related
I am trying to create a method which returns a single String (not String array) containing information for all objects in my array list. I know that strings are immutable so I am really struggling with how to add information from each object.
This is my method where I am trying to return a single string:
public String infoForEachItem ()
{
String info;
for (int y =0; y < items.size(); y++)
{
info = "ID: " + items.get(y).getId() + "\n" +
"Name : " + items.get(y).getName() + "\n" +
"Cost: " + items.get(y).getCost() + "\n";
return info;
}
}
As you can see, I want to create a string containing the Id, name, and cost of EACH item as a single string. It won't let me return within a for loop. Is there anyway to append something to the end of String?
StringBuilder
Use StringBuilder to build up text by appending multiple times.
Here is some code expanding on comment by Federico klez Culloca:
public String infoForEachItem ()
{
StringBuilder result = new StringBuilder();
for (Item item : items) {
result.append("ID: ").append(item.getId()).append('\n');
result.append("Name: ").append(item.getName()).append('\n');
result.append("Cost: ").append(item.getCost()).append("\n\n");
}
return result.toString();
}
You can chain the calls to .append as you think it is suitable, and there are overloads of the method for many parameter types.
I am trying to add an object to an array list and have the following -
public static void main(String[] args) {
authors Authors = new authors();
ArrayList<authors> tabAuthors = new ArrayList<authors>();
Authors.setAuthId(1);
Authors.setAuthName("Roald Dahl");
System.out.println(Authors.toString());
tabAuthors.add(Authors);
Authors.setAuthId(2);
Authors.setAuthName("Julia Donaldson");
System.out.println(Authors.toString());
tabAuthors.add(Authors);
for (int counter =0; counter < tabAuthors.size(); counter++) {
System.out.println(tabAuthors.get(counter).getAuthId() + " " + tabAuthors.get(counter).getAuthName() );
}
}
}
The authors class
public class authors {
private int authId;
private String authName;
public int getAuthId() {
return authId;
}
public void setAuthId(int authId) {
this.authId = authId;
}
public String getAuthName() {
return authName;
}
public void setAuthName(String authName) {
this.authName = authName;
}
#Override
public String toString() {
return "authors{" +
"authId=" + authId +
", authName='" + authName + '\'' +
'}';
}
}
I was expecting the code to return -
1 Roald Dahl
2 Julia Donaldson
Instead, I am getting -
2 Julia Donaldson
2 Julia Donaldson
Why is the array list not reflecting the first object values ?
Because you create only one object and override second time when you set properties.
You need to create new object when you insert second object.
You are setting the value Julia Donaldson on the same Object. reference the variable Authors to a new object and the problem is solved.
authors Authors = new authors();
ArrayList<authors> tabAuthors = new ArrayList<authors>();
Authors.setAuthId(1);
Authors.setAuthName("Roald Dahl");
System.out.println(Authors.toString());
tabAuthors.add(Authors);
Authors = new Authors(); //Reference Authors to a new object here, or else
//you're using the same object and you'll overwrite the value Roald Dahl with
//Julia Donaldson
Authors.setAuthId(2);
Authors.setAuthName("Julia Donaldson");
System.out.println(Authors.toString());
tabAuthors.add(Authors);
In addition to the answer above by #Maurice, you can also add a constructor in authors class to set values for every object.
public authors(int authId, String authName) {
super();
this.authId = authId;
this.authName = authName;
}
In your main(), create two objects as below and add them to the list:
public static void main(String[] args) {
Authors authors1 = new Authors(1, "Roald Dahl");
Authors authors2 = new Authors(2, "Julia Donaldson");
List<Authors> tabAuthors = new ArrayList<Authors>();
System.out.println(authors1.toString());
tabAuthors.add(authors1);
System.out.println(authors2.toString());
tabAuthors.add(authors2);
for (int counter = 0; counter < tabAuthors.size(); counter++) {
System.out.println(tabAuthors.get(counter).getAuthId() + " " + tabAuthors.get(counter).getAuthName());
}
}
Output:
authors{authId=1, authName='Roald Dahl'}
authors{authId=2, authName='Julia Donaldson'}
1 Roald Dahl
2 Julia Donaldson
Thanks for your prompt responses.
I added the below in the code as I need to add indeterminate number of objects -
tabAuthors.add(new authors(authId,authName,authCountry,numBooks));
and declared authId,authName,authCountry,numBooks as variables.
The object values are being fetched from a database table.
I've got 2 classes, car extends vehicle, Why, when I'm trying to print a new created car object the output isn't equal as I thought.
I'm running it on Eclipse, java 11
public class vehicle_13 {
private int years;
public vehicle_13(int y) {
years=y;
}
public int years() {
return years;
}
public String driving() {
return "Can drive";
}
public int speed() {
return 50;
}
public String toString() {
return "years = "+years()+"\n"+this.driving()+"\n"+"speed = "+this.speed()
+"\n"+this.money_per(); // driving() = this.driving()
}
public int money_per() {
return years*10;
}
}
public class car_13 extends vehicle_13 {
public car_13(int y) {
super(0);
}
public int speed() {
System.out.println(super.driving());
return super.speed()*2;
}
}
I expect the output of this car object .toString() to be:
years = 0
Can drive
Can drive
speed = 100
0
but the actual output is:
Can drive
years = 0
Can drive
speed = 100
0
When you concatenate the string like this:
return "years = " + years() + "\n" + this.driving() + "\n"
+ "speed = " + this.speed() + "\n" + this.money_per();
It has to execute each of the methods before it creates the string. After all, it's the result of executing the method that gets added to the string. So the println in the speed method is called when this.speed() is evaluated, then the concatenated string is returned by toString, and then the result is passed to System.out.println. So the println in speed runs before the println in main, not in the middle of it.
P.S: Long concatenation like this, is better suited to the String.format method
return String.format("years = %d\n%d\nspeed = %d\n%d",
years(), driving(), speed(), money_per());
You have called super.driving in the sub-class and that is what is evaluated first. Therefore it prints out "Can drive" first, before the result of the toString as you expected.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
Disclaimer: I'm a beginner so feel free to point stuff out...
I have a superclass composed by an array of int with 8 values, now i want to create a subclass to randomly pick 4 items in the array and store them in another Object.
Superclass:
public class SideDeck{
public static final int MaxValue = 6;
public static final int MinValue = -6;
public static final int MaxArrayValue = 8;
public final int[] sidecards = new int[MaxArrayValue];
public SideDeck(){
for(int i=0;i<MaxArrayValue;i++){
sidecards[i]=0;
}
}
public SideDeck(int sidecards1,int sidecards2,int sidecards3,int sidecards4,int sidecards5,int sidecards6, int sidecards7, int sidecards8){
sidecards[0]=sidecards1;
sidecards[1]=sidecards2;
sidecards[2]=sidecards3;
sidecards[3]=sidecards4;
sidecards[4]=sidecards5;
sidecards[5]=sidecards6;
sidecards[6]=sidecards7;
sidecards[7]=sidecards8;
}
public boolean ValidSidedeck(){
int check=0;
if (sidecards[0]!=0) {
for(int i=0;i<MaxArrayValue;i++){
if ((sidecards[i] > MinValue) && (sidecards[i] < MaxValue)){
check=1;
} else{
check=0;
break;
}
}
} else {
check=0;
}
if (check==1){
return true;
} else {
return false;
}
}
public String toString(){
String s="";
for(int i=0;i<MaxArrayValue;i++){
s+=(" || Card n° " + (i+1) + " = " + sidecards[i]);
}
return s;
}
public void ResetSidedeck(){
if (sidecards[0]!=0) {//why check it? what if we just run it?
for(int i=0;i<MaxArrayValue;i++){
sidecards[i]=0;
}
}
}
}
Subclass: (Not really sure what to do here… ) Basically it should pick 4 random positions from the .super and store them here, just that i have no clue how to create the object this way. And passing the super as constructor doesn't seem right since it's gonna pass the Object and not the array(and i don't need the full array anyway). Main thing is that i wanna keep the superclss like that, maybe just adding a method there so extract the 4 values..and passing them as arguments…?
import java.lang.Math;
public final class PlayableSideDeck extends SideDeck{
private final static int MaxCArrayValue=4;
public final int[] sidecardsPlay = new int[MaxCArrayValue];
public PlayableSideDeck(SideDeck sidecards){
/* sidecardsPlay[0]=0;
sidecardsPlay[1]=0;
sidecardsPlay[2]=0;
sidecardsPlay[3]=0;*/
// SetDeck();//<-Can i call a private method in the constructor
}
public void SetDeck(){
/* for(int j=0;j<4;j++){
int position=(super.sidecards[PickDeck()]);//<--this is the main problem.. since it's gonna call the object i guess.
sidecards[j]=position;
System.out.println(/*"i= " + i + *//* " ||| j= " + j + "|||| new sidecard= " + sidecards[j] + " |||| old sidecard=" + super.sidecards[PickDeck()]);
}*/
for(int j=0;j<MaxCArrayValue;j++){
sidecardsPlay[j]=(super.sidecards[PickDeck()]);
System.out.println(/*"i= " + i + */ " ||| j= " + j + "|||| new sidecard= " + sidecardsPlay[j] + " |||| old sidecard=" + super.sidecards[PickDeck()] + "|| random= " + PickDeck());
}
}
public int PickDeck(){
return ((int)(Math.random() * 8));
}
public String toString(){
String s="";
for(int i=0;i<MaxCArrayValue;i++){
s+=(" || Card n° " + (i+1) + " = " + sidecards[i]);
}
return s;
}
}
Thanks.
I'm not sure how you plan to use PlayableSideDeck, so I'll answer answer this two ways and you can pick the most fitting answer.
First, as the book Effective Java (by Josh Bloch) points out, you should favor composition over inheritance. By using composition you have your answer to the question of whether you should pass an instance of SideDeck to the constructor of PlayableSideDeck - you will have to since you won't be inheriting any access to SideDeck. Anyway, I'd recommend reading Item 16 in the book (google for it, there are copies available online) and see if composition doesn't better fit your needs.
Second, if you decide to go with inheritance, you don't need to pass an instance of SideDeck to the constructor of PlayableSideDeck. This is because when you create an instance of PlayableSideDeck you are automatically creating an instance of SideDeck along with it. All constructors in Java will implicitly call super() (which is the superclasses's default constructor) if you don't explicitly provide another such call yourself. For example, you could prevent the implicit call to super() like so:
public class BaseClass {
protected String strValue;
public BaseClass () {
strValue = "";
}
public BaseClass (String str) {
strValue = str;
}
}
public class SubClass extends BaseClass {
private int intValue;
SubClass (String str, int i) {
super (str);
intValue = i;
// note that since strValue is protected, SubClass can access directly
System.out.println ("strValue = " + strValue);
}
}
In this example, if you call new SubClass ("foobar") then you will see strValue = foobar printed on the console.
If BaseClass didn't have a zero argument constructor you would, in fact, be required to call super(str) since the compiler wouldn't be able to figure out how to do it for you.
Also, since you asked, here are a few other tips and pointers:
In the constructor SideDeck() you explicitly initialize all values of the array to 0, which isn't necessary. They will already all be 0. If you needed to init them to 0 then you'd be better off avoiding code duplication by calling ResetSideDeck. Speaking of which, you can shorten that code to Arrays.fill (sidecards, 0); (be sure to import java.util.Arrays).
Yes, you can call private methods from a constructor - but only private methods that are part of the local class, not any of the superclasses (you can, however, call protected methods of superclasses).
You're right about not checking sidecards[0] == 0 since there's little efficiency to be gained unless MaxArrayValue becomes very large.
Your class member variables such as sidecards should be private (or maybe protected if you need to access them from a subclass). Use getter/setter methods to access them.
Lastly, Java naming conventions would tell you to use a lower-case letter for method names (e.g. setDeck, pickDeck, resetDeck, etc.), and for even more idiomatic Java you could rename ValidaDeck to isValidDeck (since it returns a boolean). For the constants such as MaxArrayValue the convention is to use all upper-case with underscores between words, e.g. MAX_ARRAY_VALUE.
Hope this all helps!
I am completely new to java. I have searched for hours upon hours for the solution to this problem but every answer involves passing args or using a void which I do not do in this situation.
I have two java files, one for Room class, and one for TourHouse class. I am trying to create a new Room in the TourHouse class. Here is my error, it's driving me nuts, I've tried everything I am capable of understanding. Thank you in advance.
HouseTour.java:15: error: constructor Room in class Room cannot be applied to given
types;
{
^
required: String, String
found: no arguments
reason: actual and formal arguments differ in length
Here is the Room class, will have 7 rooms total once I can figure this out
// Room.java
import java.util.*;
public class Room
{
// Define Instance Variables
private String name;
private String description;
// Define Constructor
public Room(String theName, String theDescription)
{
name = theName;
description = theDescription;
}
public String toString( )
{
return "The " + name + "\n" + description + "\n";
}
}
Here is the HouseTour class
import java.util.*;
public class HouseTour extends Room
{
// Define Variables
public Room[ ] rooms = new Room[7];
//Define Constructor
public HouseTour( )
{
rooms[0] = new Room("Living Room", "Mayonnaise and Brill Grates, Michaelsoft");
rooms[1] = new Room("Basement", "Hopefully no dead bodies down here...");
}
// this is horrible and not right
public String rooms( )
{
for (int i = 0; i <=7; i++)
{
String output = "House Rooms included in tour\n";
String output2 = output + rooms.toString() + "\n";
return output2;
}
}
}
EDIT: Solved but still need help here because I am complete n00b, :(
// this is horrible and not right
public String rooms( )
{
output = "House Rooms included in tour\n";
for (int i = 0; i <=7; i++)
{
output += rooms[i]; // I can't do this but how do i?
}
return output.toString(); // do I do this?
}
}
What I am doing is trying to learn java by converting the ruby projects I have created. So in ruby you say:
def rooms
output = "House Rooms included in tour\n"
#rooms.each do |r|
output += r.to_s + "\n"
end
return output
end
Edit: Still trying, any ideas?
added public String s; and public String output; to declarations
// this is horrible and not right
public String rooms( )
{
s = ""
output = "House Rooms included in tour\n";
for (int i = 0; i <=7; i++)
{
s += rooms[i];
}
s.toString() // I don't know
return output + s; // do I do this?
}
}
Edit: Solved thanks to Hovercraft Full Of Eels
Ah, I see your problem: HouseTour extends Room. Don't do this! HouseTour is not a more specific case of a Room type and so should not extend this class. It does not fulfill the "is-a" rule, and would be similar to trying to define Bus as a child class of SchoolKid. Just like a Bus isn't a type of SchoolKid but rather contains SchoolKids, a HouseTour isn't a Room but rather contains Rooms. It fulfills the has-a relationship, not the is-a relationship.
If the inheritance were proper in this situation, your HouseTour constructor would need to call the Room super constructor and pass in two String parameters:
// Don't do this!!!
public class HouseTour extends Room {
public HouseTour() {
super("foo", "bar");
....
}
But having said that, again inheritance is not proper here -- just get rid of extends Room, and you're home free.
e.g.,
public class HouseTour { // no extends!
private Room[] rooms; // has-a not is-a
public HouseTour() {
// don't call super here
}
Also, as per my comment, this will give you ugly output: rooms.toString()
Instead iterate through the Array and get the toString() result from each Room item in the array.
Edit
Suggestions on your rooms() method:
Create a String or StringBuilder before the loop.
Build up the String or StringBuilder inside the loop.
Return the String or StringBuilder#toString after the loop.
Inside of the loop get the toString() from the current Room item in the list.
You will need to check that the rooms[i] item isn't null before calling a method on it.
Edit 2
You state that this:
public String rooms( )
{
output = "House Rooms included in tour\n";
for (int i = 0; i <=7; i++)
{
output += rooms[i]; // I can't do this but how do i?
}
return output.toString(); // do I do this?
}
is causing problems, but you don't specify the problem.
Myself, I'd do something like:
public String rooms( ) {
// declare your String locally, not globally in the class
String output = "House Rooms included in tour\n";
// again, avoid using "magic" numbers like 7
for (int i = 0; i < rooms.length; i++) {
output += rooms[i].toString(); // **** you must extract Room's String
}
return output; // no need to call toString() on a String
}