In: Computer Science
Making Rectangle comparator an inner class
3.5. A very specialized class, such as the RectangleComparator, can be defined inside the method that uses it.
Reorganize your program so that the RectangleComparator class is defined inside the main method of your test class.
What is your main method now?
Your answer :
4. There are at least two good reasons why you might choose to build a class as an inner class inside of another containing class:
1) The inner class will never be used to instantiate objects outside of the containing class, so we are effectively hiding the inner class from other classes.
2) The inner class needs access to data that is defined inside the containing class. In this case, the inner class is positioned in the scope of the shared variables of the containing class. As a result the containing class variables don’t need to be passed to the inner class. This is particularly handy if lots of information must be shared, as is often the case for listener classes in a graphics application.
There is one good reason not to build inner classes: Inner classes break the object-oriented notion of “data hiding” – the idea that class variables are private and are only accessible by public accessor and mutator methods in the same class. When we build inner classes we should remember that we are breaking an important object-oriented design principle and we should have a compelling reason to design in this way.
In this problem we will gain some experience working with inner classes. The Person class below contains an inner class called Memory in which we can store String objects that represent events in the life of a Person object. We have decided that class Memory will never be used outside of Person and that the Person class contains data that is needed by the Memory class. Here is the code.
import java.util.*;
public class Person
{
private String name;
private int age;
private Memory mem;
public Person(String name, int age)
{
this.name = name;
this.age = age;
mem = new Memory();
}
public String toString()
{
return "Name: " + name + '\n' +
"Age: " + age + '\n';
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public void tellAll()
{
mem.dumpMemory();
}
public void rememberAnEvent(String s)
{
mem.addLifeData(s);
}
// Start of inner class Memory
private class Memory
{
ArrayList<String> lifeData;
private Memory()
{
lifeData = new ArrayList<String>();
lifeData.add("Name: " + name);
lifeData.add("Age: " + age);
}
public void addLifeData(String datum)
{
lifeData.add(datum);
}
public void dumpMemory()
{
for (String s: lifeData)
{
System.out.println(s);
}
}
}
}
Here is a driver for the Person class.
public class PersonRunner
{
public static void main(String[] args)
{
Person aperson = new Person("Bob", 33);
aperson.tellAll();
aperson.rememberAnEvent("I was born in 1970.");
aperson.rememberAnEvent("I finished school in 2003.");
aperson.tellAll();
}
}
Notice that the private data in Person includes instance variables name and age. Look inside the inner class Memory and notice that name and age are referenced directly in the Memory constructor without invoking an accessor method. This is only possible because the Memory constructor is in the scope of name and age.
In order to understand the effects of an inner class, remove class Memory from Person and make it a standalone class. Make all the changes that are needed in each class to make the new design work.
Your answer :
import java.util.Comparator;
import java.awt.Rectangle;
public class RectangleComparator implements Comparator<Rectangle>
{
/**
Compares two Rectangle objects.
@param r1 the first rectangle
@param r2 the second rectangle
@return 1 if the area of the first rectangle is larger than the area of
the second rectangle, -1 if the area of the first rectangle is
smaller than the area of the second rectangle or 0 if the two
rectangles have the same area
*/
public int compare(Rectangle r1, Rectangle r2)
{
. . .
}
}
Here is the code to your problem,
PART 1 :
RectangleComparator.java
import java.awt.*;
import java.util.Comparator;
public class RectangleComparator {
public static void main(String[] args) {
Comparator<Rectangle> comparator = (o1, o2) -> {
int area1 = o1.height * o1.width;
int area2 = o2.height * o2.width;
return Integer.compare(area1, area2);
};
}
}
PART 2 :
Person.java
public class Person extends Memory{
private String name;
private int age;
public Person(String name, int age) {
super(name, age);
this.name = name;
this.age = age;
}
public String toString() {
return "Name: " + name + '\n' +
"Age: " + age + '\n';
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void tellAll() {
this.dumpMemory();
}
public void rememberAnEvent(String s) {
this.addLifeData(s);
}
}
Memory.java
import java.util.ArrayList;
public class Memory {
private ArrayList<String> lifeData;
public Memory(String name, int age) {
lifeData = new ArrayList<>();
lifeData.add("Name: " + name);
lifeData.add("Age: " + age);
}
public void addLifeData(String datum) {
lifeData.add(datum);
}
public void dumpMemory() {
for (String s : lifeData) {
System.out.println(s);
}
}
}
PersonRunner.java
public class PersonRunner {
public static void main(String[] args) {
Person aperson = new Person("Bob", 33);
aperson.tellAll();
aperson.rememberAnEvent("I was born in 1970.");
aperson.rememberAnEvent("I finished school in 2003.");
aperson.tellAll();
}
}
If you have any doubts feel free to ask in the comments. Also please do upvote the solution.