/* CSC 17 Lab 1 due BEFORE next week's lab The first assignment asks you to convert a C++ program into Java, then make some additions to the java program. You are expected to also have read the C++ to Java tutorial (at least first half). Type "javac progname.java" to compile source code progname.java. Then type "java progname" to run the program. Remember: if the file name is "progname.java", then the public class that contains main must be called "progname" as well. 1. The program you're asked to convert implements "Time" objects with a minutes and a seconds value. For example, 'new Time(2,15)' creates a heap-allocated object representing 2 minutes and 15 seconds. You will then implement a number of operations including adding two time values (2min 15sec plus 1min 50sec = 4min 5sec). The C++ program was written in a way so that it can be easily converted to a close java equivalent. For example, it only uses heap-allocated objects with pointers, though I didn't use smart pointers as some of you are not familiar with those. I also marked some methods "virtual" because technically there would be no java equivalent otherwise. To have std::cout call the "toString()" method in C++, you would have to overload the '<<' operator in C++. In java, this is done by inheritance ("overriding" instead of "overloading"): the toString method in your class overrides the toString method in the Object super-super class. INSTEAD OF TRYING TO EDIT THE C++ PROGRAM, YOU SHOULD TYPE IN A JAVA PROGRAM FROM SCRATCH. */ /* C++ program for managing time values with minutes and seconds: */ #include #include using namespace std; class Time { protected: // protected means values visible in time class and in subclasses int minutes; int seconds; public: Time(int m, int s) { int extra_minutes = s/60; seconds = s%60; minutes = m+extra_minutes; }//constructor Time() { // alternate constructor (also allowed in java) minutes = seconds = 0; }//alternate, default constructor. virtual int total_seconds() { return minutes*60 + seconds; } // convert Time object to printable string form: // std::to_string is available in C++ 2011 or later virtual string toString() { return to_string(minutes) + " min " + to_string(seconds) + " sec"; }// toString // increment this Time object by one second destructively (changes existing // object) virtual void tick() { seconds++; minutes += seconds/60; seconds = seconds%60; }//tick // compare this Time value with other Time value, return 0 if times are // equal, negative value if this time is less than other time and // positive value if this time is greater than other time. For example, // 1 min 30 seconds is less than 2 minutes and 10 seconds virtual int compareTo(Time* other) { int total1 = this->total_seconds(); int total2 = other->total_seconds(); return total1 - total2; }// compareTo // add a pair of Time values non-destructively (produces a new object, // does not change any existing object). Take pointer to other Time object // and returns pointer to newly heap-allocated Time object virtual Time* add(Time* other) { int other_seconds = other->total_seconds(); int s = seconds + other_seconds; int m = minutes + s/60; s = s%60; return new Time(m,s); }//add }; //Time class // overload "<<" on cout so printing will auto-invoke toString method ostream& operator <<(ostream& outstream, Time* t) { outstream << t->toString(); return outstream; } // this is not necessary in Java because toString overrides Object.toString void main2(); // method defined after main (see Part 2) int main(int argc, char* argv[]) { Time* t1 = new Time(2,15); t1->tick(); Time* t2 = new Time(1,44); Time* t3 = t1->add(t2); cout << "t1: " << t1 << endl; cout << "t2: " << t2 << endl; cout << "sum Time: " << t3 << endl; cout << "compare t1 and t2: " << t1->compareTo(t2) << endl; cout << "compare t1 with equivalent value: "<< t1->compareTo(new Time(0,136))<Time::tick(); hours += minutes/60; minutes = minutes%60; }//tick // note the return type is declared Time*, NOT HTime* Time* add(Time* other) override { int other_seconds = other->total_seconds(); int s = seconds + other_seconds; int m = minutes + s/60; int h = hours + m/60; s = s%60; m = m%60; return new HTime(h,m,s); }//sum };// HTime subclass of Time void main2() { Time* t1 = new Time(3,50); Time* t2 = new HTime(1,2,30); cout << t1->add(t2) << endl; Time* times[4]; times[0] = new Time(2,30); times[1] = new HTime(1,30,25); times[2] = new Time(5,45); times[3] = new HTime(2,0,0); Time* sum = new HTime(0,0,0); for(auto t:times) sum = sum->add(t); cout << "total time: " << sum << endl; cout << "can still compare HTimes: " << sum->compareTo(t2) << endl; cout << (new HTime(1,0,0))->compareTo(new Time(60,0)) << endl; delete t1; delete t2; // manual memory deallocation with raw pointers for(int i=0;i<4;i++) delete times[i]; // no delete[] times because the array's allocated on stack }//main2 /* This is an example of a truly object-oriented program. Look at main2(): the line `Time* t2 = new HTime(1,2,3)` is perfectly valid because HTime is a subclass of Time. So given a variable of type Time*, it could be a Time object OR an HTime object. That is, STATICALLY, as in "at compile time", the variable t2 has type Time*, whereas DYNAMICALLY, as in "at runtime", the actual object that was created has type HTIME. Another key part of this program is the int total_seconds() function, which is called from several other functions. Given Time* t, t->total_seconds() may call one of two functions: the one in Time or the one in HTime. It depends on the actual type of t at *runtime*. This is called "DYNAMIC DISPATCH" - an essential component of OOP. What I was able to achieve by arranging the program this way is POLYMORPHISM: I can add any pair of Time* Objects, even if one is a Time and the other one an HTime, because both add funtions call total_seconds, which will dispatch to the correct version. I can also, as demonstrated in main2, declare an array of Time* objects. The "static type" of each object T[i] is Time* but the "dynamic type" of each of these objects depends on what's assigned to it at runtime. Finally, notice that the compareTo function was not overridden in the subclass: there is no needed to. The inherited version will call the right version of total_seconds. I can still call compareTo on a Pair of HTime objects, or between an HTime object and a Time object. The challenge of this assignment is to try to write the equivalent program in Java (including main2). You may have to do some research and some experimentation to get it to work the same way. */