Chaps, I have just read about java interfaces and there is a nice exercise in my book that I would like to attempt, so I was wondering if you could help me to identify the best way to go about it. Here's the exercise:
"Create 3 small classes unrelated by inheritance - classes Building, Car and Bicycle. Give each class some unique appropriate attributes and behaviours that it doesn't have in common with other classes. Write an interface CarbonFootprint with a getCarbonFootprint method. Have each of your classes implement that interface so that its getCarbonFootprint method calculates an appropriate carbon foorptint for that class (check out a few sites that explains how to calculate carbon footprint).
Write an application that creates objects oh each of the 3 classes, places references to those objects in ArrayLists<CarbonFootprint>, then iterates through the ArrayLists, polymorphycally invoking each object's getCarbonFootprint method. For each object print some identifying information and the object's carbon footprint".

Now, first of all, let me say that I don't really care about the accuracy of the carbon footprint calculation, because I am not going to build an application that somebody will actually use (there are plenty of online calculators for that), this is just an exercise aimed at helping me to understand interfaces a bit more and the usage of ArrayLists<T> which I have never used.

I had a look at how the footprint is calculated and these are the formulas I was thinking to use:
For a car:
carbon footprint = ((averageYearlyMiles * AverageMPG) * 9kg/gallon) because allegedly one gallon of gas emits 9kg of co2. (source: http://www.motherearthnews.com/nature-and-environment/carbon-footprint-calculator.aspx#axzz2WOzrsqNS)

For a house:
carbon footprint = monthly electricity kWh * 12 source http://www.howany.com/how-to-calculate-carbon-footprint/

For a bike
carbon footprint = miles * 34 (takes 34 calories to bike a mile apparently) source: http://twtitw.firebus.com/node/100

Obviously if you have any suggestion as to how to calculate that, let me know.
The questions I have are:
1) is it worth doing some pseudocode? I mean in this program I will only create some objects and then calculate the carbon footprint.
2)what sort of relevant attribute and behaviours do you think each of the classes should have? I was thinking that there won't be many. For example:
Car:
-relevant behaviours? Can't think of any
attributes:
-miles in a year
-MPG
-kg of co2 (constant amounting to 9)

Bike:
-relevant behaviours? Can't think of any
attributes:
-miles in a year
-calories per mile (constant amounting to 34)

house
-relevant behaviours? Can't think of any
attributes:
-monthly Kwh
-months (constant amounting to 12)

Is there anything else I need?
thanks

  1. If you think that the problem at hand is not that hard, you can only sketch it and start writing code (for larger projects a deeper analysis is required).
  2. Since you have to compute the carbon footprint of each of those objects, and you have the formulas, I'm guessing that you can use as attributs those concepts from the formulas. Still, you can expand to whatever you want your classes (e.g. building street, city, country, building number, area postal code etc., cat engine, car S/N etc., bike type, components, producer etc.), but for a small example I'll go with the concepts from your formulas.
    Also, I'll have some name to the classes also, since you must tell if it's a building, or a car or a bike. But overall, for this small example, what you've identify is ok.

Edited 3 Years Ago by Lucaci Andrew

Since you don't actually do anything with those classes it doesn't matter what attributes they have, so maybe this example is a bit too simple?
Do you still have your code for two or more console-based games (tictactoe, hangman, scissors/paper/rock or whatever)?. If so it may be interesting to package those as classes into a simgle games console app where you can chose which games to play and (here's the relevenat bit) implement an interface to start a game, and get player statistics (start(), get name of game, date/time played, win/lost ...) so they all can be started and contribute to the statistics via that interface. Just a thought...

Edited 3 Years Ago by JamesCherrill

JamesCherrill, it would be a really really good idea but unfortunately I only have the tic tac toe and judging from a quick look at my computer I don't think I have developed any other game in java unfortunately. Also if it wasn't for the fact that I have to crack on with the theory I would almost be tempted to attempt one or two more games, but I am quite behind, so I tink I will pass on this, but I do appreciate the great idea!
Also you're quite right in saying that the above exercise is a bit too simple, but - believe it or not - it is the most difficult for the section I am reading : - )! I will give it a go, I suppose no programming exercise is a waste of time.
I suppose that, since the 3 classes are that simple I won't bother thinking about any possible method other than the one specified in the exercise like Lucaci Andrew suggested, and develop with what I have. I will leave the thread open in case I get stuck

good job I have left it open...I am having some issues with the ArrayList<t>. This is all my code broken down in classes:

INterface:

/*CarbonFootprint interface. File CarbonFootprint.java*/
public interface CarbonFootprint{
    double getCarbonFootprint();//calculates the carbon footprint
}//end of interface

BIke:

/*Bike.java: Bike class*/
public class Bike implements CarbonFootprint{
    private double yearlyMiles;
    private final int caloriesPerMile = 34;

    //constructor
    public Bike( double miles ){
        yearlyMiles = miles;
    }//end of constructor

    public double getYearlyMiles(){
        return yearlyMiles;
    }

    public void setYearlyMiles( double miles ){
        yearlyMiles = miles;
    }

    @Override
    public String toString(){
        return String.format("%s: %.2f",
            "Yearly miles are ", getYearlyMiles() );
    }

    @Override
    public double getCarbonFootprint(){
        return yearlyMiles * caloriesPerMile;
    }

}//endnof Bike class

Building:

/*Building.java: Building class*/
public class Building implements CarbonFootprint{

    private double averageMonthlyKwh;
    private final int months = 12;
    //private double carbonFootprint;

    //constructor
    public Building( double monthlyConsumption ){
        averageMonthlyKwh = monthlyConsumption;
    }//end of constructor

    public void setAverageMonthlyKwh( double monthlyConsumption ){
        averageMonthlyKwh = monthlyConsumption;
    }

    public double getAverageMonthlyKwh(){
        return averageMonthlyKwh;
    }

    @Override 
    public String toString(){
        return String.format("%s: %.2f\n", 
        "the monthly consumption is ", getAverageMonthlyKwh() );
    }

    @Override
    public double getCarbonFootprint(){
        return getAverageMonthlyKwh() * months;
    }

}//end of Building class

Car:

/*Car.java: Car class*/
public class Car implements CarbonFootprint{
    private double averageYearlyMiles;
    private double averageMPG;
    private final int kgCO2PerMile = 9;

    //constructor
    public Car( double miles, double MPG ){
        averageYearlyMiles = miles;
        averageMPG = MPG;
    }//end of constructor

    public void setAverageYearlyMiles( double miles ){
        averageYearlyMiles = miles;
    }

    public void setAverageMPG( double MPG ){
        averageMPG = MPG;
    }

    public double getAverageYearlyMiles(){
        return averageYearlyMiles;
    }

    public double getAverageMPG(){
        return averageMPG;
    }

    @Override
    public String toString(){
        return String.format( "%s: %.2f \n%s: %.2f \n",
            "Average yearly miles is ", getAverageYearlyMiles(),
            "Average MPG is ", getAverageMPG() );
    }

    @Override
    public double getCarbonFootprint(){
        return (( getAverageYearlyMiles() * getAverageMPG() ) * kgCO2PerMile );
    }

}//end of Car class

Test Class:

/*CarbonFootprintInterfaceTest.java: testing the interface*/
import java.util.ArrayList;

public class CarbonFootprintInterfaceTest{
    public static void main( String[] args ){

        ArrayList< CarbonFootprint > categories = new ArrayList< CarbonFootprint >();//creates array of objects of type CarbonFootprint
        categories[0] = new Bike( 200.00 );
        categories[1] = new Building( 4000.52 );
        categories[2] = new Car( 5845.25, 20.5 );
        System.out.println(" Data of each object:\n ");

        for( CarbonFootprint currentObject : categories ){
            System.out.printf("%s \n%s: %.2f\n",
                categories.toString(),
                "Carbon footprint is ", categories.getCarbonFootprint());
        }//end for loop     
    }//end of main
}//end of CarbonFootprintInterfaceTest

I would have thought I could use ArrayLists like normal arrays and assign each element a value, like above, but I am getting the followin error messages:

antobbo@antobbo-xps17-ubuntu:~/Documents/dell xps/My documents/java/tests/carboFootprint$ javac *.java
CarbonFootprintInterfaceTest.java:8: error: array required, but ArrayList<CarbonFootprint> found
        categories[0] = new Bike( 200.00 );
                  ^
CarbonFootprintInterfaceTest.java:9: error: array required, but ArrayList<CarbonFootprint> found
        categories[1] = new Building( 4000.52 );
                  ^
CarbonFootprintInterfaceTest.java:10: error: array required, but ArrayList<CarbonFootprint> found
        categories[2] = new Car( 5845.25, 20.5 );
                  ^
CarbonFootprintInterfaceTest.java:16: error: cannot find symbol
                "Carbon footprint is ", categories.getCarbonFootprint());
                                                  ^
  symbol:   method getCarbonFootprint()
  location: variable categories of type ArrayList<CarbonFootprint>
4 errors
antobbo@antobbo-xps17-ubuntu:~/Documents/dell xps/My documents/java/tests/carboFootprint$ 

Lists use methods to add and access elements, not the [] notation. eg categories.add(new Bike(200.00)); Check the ArrayList API documentation for all the methods you can use.

oh I see, thanks for that JamesCherrill. I sort of knew that those methods existed but I thought I could also use the normal array notation, sorry. It crossed my mind to check the API but I must admit that I am a bit reluctant to do so because I always get confused when I do it, there is so much information there and I never know what I look for.
So in the above suggestion you are using this method:

add(E e)
Appends the specified element to the end of this list.

I have made the changes as you suggested to have this

ArrayList< CarbonFootprint > categories = new ArrayList< CarbonFootprint >();//creates array of objects of type CarbonFootprint
        /* categories[0] = new Bike( 200.00 );
        categories[1] = new Building( 4000.52 );
        categories[2] = new Car( 5845.25, 20.5 ); */
        categories.add( new Bike( 200.00 ));
        categories.add( new Building( 4000.52 ));
        categories.add( new Car( 5845.25, 20.5 ));
        System.out.println(" Data of each object:\n ");

I now have another error, a "cannot find symbol". Obviously I googled it, trying to understand what this is about but I am still not sure sorry:

antobbo@antobbo-xps17-ubuntu:~/Documents/dell xps/My documents/java/tests/carboFootprint$ javac *.java
CarbonFootprintInterfaceTest.java:19: error: cannot find symbol
                "Carbon footprint is ", categories.getCarbonFootprint());
                                                  ^
  symbol:   method getCarbonFootprint()
  location: variable categories of type ArrayList<CarbonFootprint>
1 error

Completely blank, I have no idea. The variable categories is of type arrayList, but it calls a double function, so it should return a double value...

categories is an Object of type ArrayList, and ArrayLists do not have a getCarbonFootprint() method.
You must get one or more actual CarbonFootprint objects from tyhe list, then use it/them to call CarbonFootprint's getCarbonFootprint() method. eg

ArrayList<String> strings = .....
strings.toLowerCase(); // ERROR = ArrayLists do not have that method
strings.get(0).toLowerCase(); // correct
for (string s : strings) {
   s.toLowerCase(); // correct
}

Edited 3 Years Ago by JamesCherrill: Fixed typo: [0] should be (0), sorry

Oh i see, I think this is the first time I came across this sort of problem (can't quite understand why I haven't come across this before in any other program!). On reflection thought, it makes sense. So effectively, in my code only objects of type CarbonFootprint have the getCarbonFootprint() method because it has been declare inside the interface CarbonFootprint. That said I don't understand what difference it makes if I get an object from the list and use it to call the method (the object still doesn't have that particular method assigned to it unless the get() does some magic! ).
If I amend my code to be the below (haven't compiled yet)

        categories.add( new Bike( 200.00 ));
        categories.add( new Building( 4000.52 ));
        categories.add( new Car( 5845.25, 20.5 ));
        categories.get( 0 ).getCarbonFootprint();
        categories.get( 1 ).getCarbonFootprint();
        categories.get( 2 ).getCarbonFootprint();
        System.out.println(" Data of each object:\n ");

        for( CarbonFootprint currentObject : categories ){
            System.out.printf("%s \n%s: %.2f\n",
                categories.toString(),
                "Carbon footprint is ", categories.getCarbonFootprint());
        }//end for loop     
    }//end of main

is it necessary to call categories.getCarbonFootprint() so many times prior to the call inside the for loop?
thanks

Use categories.get(#) to get individual elements of the arraylist. Use a for each loop to get all elements of the arraylist. Use one or the other, not both (usually, that is). JamesCherrill was just showing you both at the same time just to compare.

Anyway, inside your for loop, lines 11 and 12, since you assigned each element of categories to currentObject, use currentObject.toString() and currentObject.getCarbonFootprint()

I don't understand what difference it makes if I get an object from the list and use it to call the method (the object still doesn't have that particular method assigned to it

Not so! You declare categories like this: ArrayList<CarbonFootprint> categories
ie categories is an ArrayList containing only CarbonFootprint objects (objects that implement the CarbonFootprint interface). So the compiler will prevent you adding any object that is not a CarbonFootprint, and equally knows that any object you get from that ArrayList wil be a CarbonFootprint, and will therefore have the getCarbonFootprint() method.

As for the rest... scudzilla already said it.

ahhh, yes, sorry I have been thick as usual! It makes sense now, I have created a currentObject variable and I wasn't even using!
Ok works now, I have changed the for loop as follow (I am also getting the class name to identify which object I am talking about):

for( CarbonFootprint currentObject : categories ){
            System.out.printf("\n%s: %s \n%s %s: %.2f\n",
                "Details for ", currentObject.getClass().getName(),
                currentObject.toString(),
                "Carbon footprint is ", currentObject.getCarbonFootprint());
        }//end for loop

thanks for your help

This question has already been answered. Start a new discussion instead.