just wondering what this error means and how I should fix this.
Error: The type Student must implement the inherited abstract method java.lang.Comparable.compareTo(java.lang.Object)
I am trying to implement this so I can use the class's compareTo Method.
Thanks so much for your help!
import java.util.*;
import java.io.*;
public class Student implements Comparable
{
private String name;
private double gpa;
public Student()
{
name = "";
gpa = 0.0;
}//end default constructor
public Student(String n, double g)
{
name = n;
gpa = g;
}//end two arg constructor
public double getGPA()
{
return gpa;
}
public String getName()
{
return name;
}
public void setGPA(double g)
{
this.gpa = g;
}
public void setName(String n)
{
this.name = n;
}
public String toString()
{
return " Name: " + name + " GPA: " + gpa;
}
public static void compareTo()
{
}
}//end class
All you have to do is implement the comparable interface and override the compareTo() method in the class you wanted to be sorted. Inside the compareTo method you must mention on which basis your object should be sorted. The below code will be helpful in this:
public class Student implements Comparable<Student>
{
private String name;
private double gpa;
public Student()
{
name = "";
gpa = 0.0;
}//end default constructor
public Student(String n, double g)
{
name = n;
gpa = g;
}//end two arg constructor
public double getGPA()
{
return gpa;
}
public String getName()
{
return name;
}
public void setGPA(double g)
{
this.gpa = g;
}
public void setName(String n)
{
this.name = n;
}
public String toString()
{
return " Name: " + name + " GPA: " + gpa;
}
public Integer compareTo(Student student)
{
// if object is getting sorted on the basis of Name
return this.getName().compareTo(student.getName())
// if object is getting sorted on the basis of gpa
return Double.valueOf(this.gpa).compareTo(Double.valueOf(student.getGPA()));
}
}//end class
Since you are using primitive data type double instead of Object Double so we need to get the object using Double.valueOf(this.gpa)
You should use only one return statement as per your requirement.
You have to make the following changes to your code in order to implement the Comparable interface correctly.
(1) Specify the type of object your class is comparable with:
public class Student implements Comparable<Student>
(2) And the corresponding signature of the compareTo method is as follow:
public int compareTo(Student other)
And of course you have to implement the body of the compareTo method too.
If the this instance is "smaller" than the argument other then compareTo should return a negative number.
If the this instance is "larger" than the argument other then compareTo should return a positive number.
If the this instance is considered to be "of the same value" as the argument other then compareTo should return 0.
You may refer to the official java document for more information about the implementation details.
Note that Interface Comparable<T> is a generic interface. Here T is type (Class, Interface mostly). You want to compare Student with another type (Student).
So you have to pass type(T) Student to Comparable<T>.
Hence you change it to
public class Student implements Comparable<Student>
Another point you have to implement the Comparable<T> interface as same method signature and return type to Student class.
public int compareTo(Student anotherStudent)
You have written
public static void compareTo()
which not follow the interface Comparable<T> method signature and return type in Student class.
Here you should implement your domain specific logic. I don't know how you want to implement it ? You can compare the name alphabetically or base on their CGPA.
Related
I am not sure how to implement a comparable interface into my abstract class. I have the following example code that I am using to try and get my head around it:
public class Animal{
public String name;
public int yearDiscovered;
public String population;
public Animal(String name, int yearDiscovered, String population){
this.name = name;
this.yearDiscovered = yearDiscovered;
this.population = population; }
public String toString(){
String s = "Animal name: "+ name+"\nYear Discovered: "+yearDiscovered+"\nPopulation: "+population;
return s;
}
}
I have a test class that will create objects of type Animal however I want to have a comparable interface inside this class so that older years of discovery rank higher than low. I have no idea on how to go about this though.
You just have to define that Animal implements Comparable<Animal> i.e. public class Animal implements Comparable<Animal>. And then you have to implement the compareTo(Animal other) method that way you like it.
#Override
public int compareTo(Animal other) {
return Integer.compare(this.year_discovered, other.year_discovered);
}
Using this implementation of compareTo, animals with a higher year_discovered will get ordered higher. I hope you get the idea of Comparable and compareTo with this example.
You need to:
Add implements Comparable<Animal> to the class declaration; and
Implement a int compareTo( Animal a ) method to perform the comparisons.
Like this:
public class Animal implements Comparable<Animal>{
public String name;
public int year_discovered;
public String population;
public Animal(String name, int year_discovered, String population){
this.name = name;
this.year_discovered = year_discovered;
this.population = population;
}
public String toString(){
String s = "Animal name: "+ name+"\nYear Discovered: "+year_discovered+"\nPopulation: "+population;
return s;
}
#Override
public int compareTo( final Animal o) {
return Integer.compare(this.year_discovered, o.year_discovered);
}
}
While you are in it, I suggest to remember some key facts about compareTo() methods
CompareTo must be in consistent with equals method e.g. if two objects are equal via equals() , there compareTo() must return zero otherwise if those objects are stored in SortedSet or SortedMap they will not behave properly.
CompareTo() must throw NullPointerException if current object get compared to null object as opposed to equals() which return false on such scenario.
Read more: http://javarevisited.blogspot.com/2011/11/how-to-override-compareto-method-in.html#ixzz4B4EMGha3
Implement Comparable<Animal> interface in your class and provide implementation of int compareTo(Animal other) method in your class.See This Post
You would need to implement the interface and define the compareTo() method.
For a good tutorial go to - Tutorials point link
or
MyKongLink
Emp class needs to implement Comaparable interface so we need to Override its compateTo method.
import java.util.ArrayList;
import java.util.Collections;
class Emp implements Comparable< Emp >{
int empid;
String name;
Emp(int empid,String name){
this.empid = empid;
this.name = name;
}
#Override
public String toString(){
return empid+" "+name;
}
#Override
public int compareTo(Emp o) {
if(this.empid==o.empid){
return 0;
}
else if(this.empid < o.empid){
return 1;
}
else{
return -1;
}
}
}
public class JavaApplication1 {
public static void main(String[] args) {
ArrayList<Emp> a= new ArrayList<Emp>();
a.add(new Emp(10,"Mahadev"));
a.add(new Emp(50,"Ashish"));
a.add(new Emp(40,"Amit"));
Collections.sort(a);
for(Emp id:a){
System.out.println(id);
}
}
}
Possible alternative from the source code of Integer.compare method which requires API Version 19 is :
public int compareTo(Animal other) {
return Integer.valueOf(this.year_discovered).compareTo(other.year_discovered);
}
This alternative does not require you to use API version 19.
Use a Comparator...
public class AnimalAgeComparator implements Comparator<Animal> {
#Override
public int compare(Animal a1, Animal a2) {
...
}
}
This thing can easily be done by implementing a public class that implements Comparable. This will allow you to use compareTo method which can be used with any other object to which you wish to compare.
for example you can implement it in this way:
public String compareTo(Animal oth)
{
return String.compare(this.population, oth.population);
}
I think this might solve your purpose.
I have a class Person and its subclass Student:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Student extends Person {
private int grade;
public Student(String name, int grade) {
super(name);
this.grade = grade;
}
public int getGrade() {
return grade;
}
public void setGrade(int grade) {
this.grade = grade;
}
public void printDescription() {
System.out.println("Name: " + getName());
System.out.println("Grade: " + Integer.toString(grade));
}
}
So Person have getter and setter for name property and Student have only getter and setter for its new grade property, as long as a printDescription() method.
The problem is how should I call the name property in Student's printDescription() method correctly?
I implemented it like in code above considering that Student inherits getter and setter from parent class.
But at my university Java teacher asks to use it like this:
public void printDescription() {
System.out.println("Name: " + super.getName());
System.out.println("Grade: " + Integer.toString(grade));
}
So he offers to directly call parent's getter.
I think it is not the best way because in case we override name's getter in Student class, getter from Person will still be called instead.
So what approach is best in this situation to use name property?
UPD: it is important to mention that for this task there is no requirement to call specifically superclass' getter implementation, this is why I was confused by teacher's recommendation to use super.
You're correct that if you override the method in the subclass and you're using the super keyword then you'll invoke the method on the parent class.
In this case unless you wanted to guarantee that the method in the parent class was used then it's fine to just invoke the method without the super keyword and that way if you override the method then you get the behaviour you want in the subclass.
if you extends a class , it will has all properties in its superclass. instead of calling super.getName() you can just call this.getName().
I created a new class "Lecturer" which extends another class "Person", i wanted to make 2 constructors for Lecturer and one would accept a name and a stipend (just a constant to say how much pay is), the other just accepts the name and uses the default stipend set in the code. i included appropriate getters and setters. I then wrote a writeOutput method to print an output similar to this
Name: (name) which gets the name and prints it
Stipend: (stipend) same process ^
heres what i have so far
Lecturer.java
public class Lecturer extends Person{
private static String name;
static double stipend;
public Lecturer(String name) {
super(name);
}
public Lecturer(String name, double stipend) {
super(name);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getStipend() {
return stipend;
}
public void setStipend(double stipend) {
this.stipend = stipend;
}
public static void writeOutput() {
System.out.println("Name: " + name);
System.out.println("Stipend: " + stipend);
}
}
Person.java
public class Person {
/** Every Person has a name */
private String name;
/** Person requires a name */
public Person(String n) {
this.name = n;
}
/** return this Person's name */
public String getName() {
return this.name;
}
/** Change this Person's name */
public void setName(String nn) {
this.name = nn;
}
Main file (Inheritance.java)
Lines 41-53
Lecturer l1 = new Lecturer("Zachary");
Lecturer l2 = new Lecturer("Wilhelmina", 11017.00);
l1.writeOutput();
l2.writeOutput();
pause();
l1.setName("Zack");
l1.setStipend(10800.00);
l1.writeOutput();
pause();
System.out.printf("%s's stipend is $%,4.2f.\n",
l1.getName(), l1.getStipend());
System.out.printf("%s's stipend is $%,4.2f.\n",
l2.getName(), l2.getStipend());
This is the output
Name: null
Stipend: 0.0
Name: null
Stipend: 0.0
press enter...
Name: Zack
Stipend: 10800.0
The 2nd part works as it should but the first one isnt and i tried to change the code but nothing is working properly.
In Lecturer you are declaring another name variable. This variable is separate from the name variable declared in Person. The call to the superclass constructor is setting the name variable in Person, not in Lecturer. But you don't need the second variable; remove it. You can access the name in Person via the getName method you've already declared. This means that you also don't need to re-declare getName and setName in Lecturer, so the Lecturer class can inherit them.
Also, in Lecturer, the two variables you've declared shouldn't be static. Per the above reasoning, name shouldn't even be there, but even if it should be there, it shouldn't be static. The variable stipend should be there, but it shouldn't be static. When you declare a member variable static, then there is only one variable for the entire class, no matter how many instances you create, which doesn't sound like what you want.
Your constructors should initialize stipend.
You have a static variable inside Lecturer which has the same name as the inherited one from Person and your getter is referring to that static one - are you sure you want these static variables? For completeness if you really want to keep the static one and the inherited one with the same name then change your getter to read return this.name; which will return the inherited name instance variable.... But that method can be inherited from Person class...
There are two name fields in your program , one is private static String name; in Lecturer.java and another is private String name; in person.java .
The thing is that you are just calling Lecturer javs's name field but not setting it.
Fixed the project based on rgettman answer.
Lecturer class should look like this:
public class Lecturer extends Person {
double stipend = 9144;
public Lecturer(String n) {
super(n);
}
public Lecturer(String n, double stipend) {
super(n);
this.stipend = stipend;
}
public double getStipend() {
return stipend;
}
public void setStipend(double stipend) {
this.stipend = stipend;
}
public void writeOutput() {
System.out.println("Name: " + this.getName());
System.out.println("Stipend: " + getStipend());
}
}
It seems odd that this is not working as I expected. I wrote a simple java class that implements Comparable interface and override the compareTo() method. However, It doesn't let me pass arguments of specific type other than Object. I looked on other guys' codes online which they did used other typed objects and I copied their code into eclipse and still I got the same error.
My question is; what I have to do to compare this object with object of type lets say Person. I do have the same issue with Comparator Interface (compare() method).
This code is the one I found it online.
public class Person implements Comparable {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public int getAge() {
return this.age;
}
public String getName() {
return this.name;
}
#Override
public String toString() {
return "";
}
#Override
public int compareTo(Person per) {
if(this.age == per.age)
return 0;
else
return this.age > per.age ? 1 : -1;
}
public static void main(String[] args) {
Person e1 = new Person("Adam", 45);
Person e2 = new Person("Steve", 60);
int retval = e1.compareTo(e2);
switch(retval) {
case -1: {
System.out.println("The " + e2.getName() + " is older!");
break;
}
case 1: {
System.out.println("The " + e1.getName() + " is older!");
break;
}
default:
System.out.println("The two persons are of the same age!");
}
}
}
You need to use generics to provide a specific type.
public class Person implements Comparable<Person> { // Note the generic to Person here.
public int compareTo(Person o) {}
}
The Comparable interface is defined something like this,
public interface Comparable<T> {
public int compareTo(T o);
}
You can make use of generics to use custom object types. Change your class definition from
public class Person implements Comparable {
to
public class Person implements Comparable<Person> {
Now you should be able to pass Person object to your compareTo method as mentioned here:
#Override
public int compareTo(Person personToCompare){
Learn more about generics here:
https://docs.oracle.com/javase/tutorial/java/generics/types.html
I keep getting the error: Student is not abstract and does not override abstract method compareTo(java.lang.Object) in java.lang.Comparable
Why is this? What this is trying to accomplish is taking a list of students and comparing them by GPA.
public class Student implements Comparable
{
private String name;
private double gpa;
public Student(String name, double gpa)
{
this.name = name;
this.gpa = gpa;
}
public String getName()
{
return name;
}
public double getGpa()
{
return gpa;
}
public String toString()
{
return "Name: " + name + " GPA: " + gpa;
}
public double compareTo(Object other)
{
Student filler = (Student)other;
if(this.getGpa() < filler.getGpa())
return -1;
else if(this.getGpa() == filler.getGpa())
return 0;
else
return 1;
}
}
To answer your question directly, you need to change the return type of compareTo() from double to int.
There are also several other modifications you should make to improve your code:
implement Comparable<Student> instead of just Comparable. This makes it so you can write public int compareTo(Student other) and only allows calling compareTo() with other Student references.
Add #Override annotations before both toString() and compareTo(). This annotation helps you avoid some common errors which the compiler cannot catch.
compareTo method returns an int and not a double.
Also using an Override annotation helps to be sure that you are overriding the method correctly. So change this
public double compareTo(Object other)
to
#Override
public int compareTo(Object other)
public double compareTo(Object other)
should be
#Override
public int compareTo(T other)
Take a look at the Comparable interface. It requires a method called compareTo, that takes an argument of type T (generic parameter), that returns an int. The method you have created doesn't implement the method specified in the interface, which is why the Java compiler is complaining.
Since the Comparable interface is genericized, you should take advantage of generics and make your class implement Comparable<Student>. When you do that, the signature of compareTo becomes:
#Override
public int compareTo(Student other)
Which is better than a raw Object, since you don't have to cast, and more importantly, you don't accidentally end up passing in something that is not a Student.
One more thing: use the #Override annotation when you implement methods from the interface. Assuming you're using a halfway-decent IDE, you would have seen an error if you had:
#Override
public double compareTo(Object other)
Since there is no method with that signature in the interface.