Java, how to inherit methods from abstract class - java

I have an abstract class Person and and interface comparable, which is also used for some other part of the program. Currently I have a method compareTo() in Person. When I try to compile, I get :
The type Student must implement the inherited abstract method
Comparable<Person>.compareTo(Person, Person)
What exactly do I have to do? I don't wont to implement this method in any of the subclasses, because I need this method for all of them, Student, Tutor, Professor, etc... Is there a better way of doing this?
Interface:
interface Comparable<Element> {
public int compareTo(Element nodeA, Element nodeB);
}
Abstract class Person:
abstract class Person implements Comparable<Person> {
protected String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
public String toString() {
return name;
}
public int compareTo(Person personB) {
int comp = this.name.compareTo(personB.getName());
return comp;
}
}
And class Student
class Student extends Person implements Comparable<Person> {
private int id;
public Student(String name, int id) {
super(name);
this.id = id;
}
public int getID() {
return id;
}
public void setID(int newID) {
id = newID;
}
public String toString() {
return id + ", " + name;
}
}

Change your interface from:
interface Comparable<Element>
{
public int compareTo(Element nodeA, Element nodeB);
}
to:
interface Comparable<Element>
{
public int compareTo(Element nodeA);
}
And make your Person class be defined as:
abstract class Person implements Comparable<? extends Person> { /* ... */ }
And make your Student (and other Person-subclasses be):
class Student extends Person { /* ... */ }
That is all.

Your Comparable interface has a method compareTo(Element nodeA, Element nodeB). This method is not defined in Student, and it's not defined in Person either. Person has the following method:
public int compareTo(Person personB)
, which doesn't override compareTo(Person nodeA, Person nodeB)
Why are you redefining the standard java.util.Comparable interface?

You should implement the method as it appears in the interface, i.e. with two arguments
public int compareTo(Person nodeA, Person nodeB)
To avoid such problems in the future use the #Override annotation:
#Override
public int compareTo(Person nodeA, Person nodeB)
This will cause a compilation error if you try to override a method, but make a mistake in its signature.
Also, consider using Java's standard Comparable.

Your Comparable<Element> class declares a method public int compareTo(Element nodeA, Element nodeB);, but in your Person class, you implement public int compareTo(Person personB), which is not the same method signature.
You need to either implement public int compareTo(Person personA, Person personB), or alter your Comparable<Element> class's method definition to be public int compareTo(Element other); to override the core Comparable class's compareTo method.
Also, as #murat mentions below in the comment, using the #Override annotation would help you out (assuming you're on Java version 1.5 or higher). If you add #Override to a method that you're not actually overriding from a superclass (such as your two-argument compareTo method), then it will be a compiler error.

You need to implement
public int compareTo(Person nodeA, Person nodeB)
In your Person class. Currently you only have:
public int compareTo(Person personB)

You need to create a compareTo method in the Student class.

interface Comparable<Element> {
public int compareTo(Element nodeA, Element nodeB);
}
It makes sense if it was either:
interface Comparator<Element> { //comparator compares two instances of same type
public int compare(Element nodeA, Element nodeB);
}
or (has to be something like this for your case):
interface Comparable<Element> { //comparable compares itself with another instance of same type
public int compareTo(Element that);
}
But for both cases, you should use the standard Java interfaces: Even though you are only using Comparable also see Comparator.

Related

Problem with Array.sort() and objects in JAVA [duplicate]

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.

One class implements from two different interfaces in Java

I have two classes that implements from two interfaces.
Here is my interfaces:
interface Identifiable {
int getId();
}
interface Greetable {
String helloMessage();
String byeMessage();
}
Here is my classes:
public class Lecturer implements Greetable, Identifiable {
private int employeeId;
private String name;
private String title;
#Override
public String helloMessage() {
return name;
}
#Override
public String byeMessage() {
return title;
}
}
public class Student implements Greetable, Identifiable {
private char examScore;
#Override
public String helloMessage() {
return "Hi";
}
#Override
public String byeMessage() {
return "Whats up";
}
}
I get the error from the classes that it has to abstract the methods from the interfaces? What does that mean?
Non-abstract classes are required to create concrete versions of any methods found in any interfaces that they're implementing, and while your classes implement concrete versions of one of the interface, the Greetable interface, you're not implementing all the methods of both interfaces, here the public int getId() method from the Identifiable interface is missing from both classes.
Solution: give both classes an int id field as well as the getId() method that returns the value held by this field.
e.g. for Student,
public class Student implements Greetable, Identifiable {
private char examScore;
private int id; // **** your classes will need this field ****
// need to set the ID somehow, either with a setter or a constructor
public Student(int id) {
this.id = id;
}
#Override
public String helloMessage() {
return "Hi";
}
#Override
public String byeMessage() {
return "Whats up";
}
#Override // **************** add this method to return the value held by id ******
public int getId() {
return this.id;
}
}
You define to implement both interfaces, but you only implemented the methods of the second interface.
So you have to implement the method getId() in both classes.
You havent implemeted the getId() method in Identifiable. If you are not implementing that method you need to make the Lecturer and Student as abstract or you need to implement the getId() method in both the classes.
In your case I think you will need to create instances of the Student and Lecturer. If so then you cannot make them as abstract, as abstract class instances cannot be created. So better implement the getId() in both the classes.
Your Student and Lecturer classes MUST implement both Greetable, Identifiable interface methods, otherwise they need to be declared as abstract classes i.e., you are missing getId() from Identifiable interface, which is causing the issues, corrected code below.
Lecturer class:
public class Lecturer implements Greetable, Identifiable {
int getId() {
return employeeId;
}
//all other existing methods
}
Student class:
public class Student implements Greetable, Identifiable {
int getId() {
return studentId;
}
//all other existing methods
}
You can look here

CompareTo of comparable does not take arguments other than Object type.

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

Java wrapper class subclass of concrete type

Let's say I have a class person as follows:
public class Person {
String name;
int age;
}
and a number of subclasses such as
public class Student extends Person {
// extra fields and methods
}
public class Teacher extends Person {
// extra fields and methods
}
Now, consider that for some application I need to assign an integer id to each person instance, but I don't want to extend the Person interface to add the getId() there and a field to hold the id. A simple solution would be to use a wrapper like:
public class PersonWrapper extends Person {
public PersonWrapper(Person p, int id) { // assign the id and other fields }
public int getId() { return id; }
}
This way the client code still works with the Person interface and a wrapped person can be
treated as a person.
The problem with this approach is that PersonWrapper is a subclass of Person and not Teacher or Student, and such a code won't work:
Teacher t = new PersonWrapper(teacher, 1);
t.giveGrade();
Of course, it's possible to create concrete wrapper types for all subclasses of Person, but I was wondering if there is a more elegant solution. The ideal solution would be something like this:
public class PersonWrapper<T extends Person> extends T
so that any PersonWrapper is a subclass of the type it wraps, but it's not possible in Java and I
suspect such definition may not be possible in any language.
In any case, how can I assign ids to subclasses without changing my client code that works with person and its subclasses, without creating a concrete wrapper for each subclass?
A wrapper does not necessarily need to extend to the class it's wrapping. So, just use PersonWrapper<T extends Person>:
public class PersonWrapper<T extends Person> {
T person;
int id;
public PersonWrapper(T person, int id) {
this.person = person;
this.id = id;
}
//getters and setters...
}
Also, a class can only extend from another class at compile time, so it's not possible that this PersonWrapper could extend from Student and Teacher at the same time, which makes impossible what you're looking for.
The only solution would be creating proxy classes on the fly using a library like cglib. For example, Spring creates proxies for classes when needs to add functionality on the fly to a class e.g. adding transaction management for methods or whole class.
The common solution to this problem is to make Person an interface.
interface Person {
public String getName();
public int getAge();
}
class ActualPerson implements Person {
private final String name;
private final int age;
ActualPerson(String name, int age) {
this.name = name;
this.age = age;
}
#Override
public String getName() {
return name;
}
#Override
public int getAge() {
return age;
}
}
class PersonWithId implements Person {
private final Person person;
private final int id;
PersonWithId(Person person, int id) {
this.person = person;
this.id = id;
}
#Override
public String getName() {
return person.getName();
}
#Override
public int getAge() {
return person.getAge();
}
}
Do not fear lots of code - the time you take writing code is insignificant compared to the time you spend regretting you didn't do it properly in the first place. Old Curmudgeon 2014
You're right that you can't do what you want to do. Assuming that you can't change the concrete classes to be, say, Student extends Person implements Identifiable, your best bet is to treat your wrapper really as a wrapper, and have a getter that returns its different elements:
public class Wrapper<T> {
private final T item;
private final int id;
...
public int getId() { return id }
public T getItem() { return item; }
}
This is a bit cumbersome to use, because you have to do something like wrapper.getItem().giveGrade() instead of just wrapper.giveGrade(). It also means you can't shove the wrapper into a List<Teacher> and then later downcast it to TeacherWrapper -- but that's a bit fragile, and there are often better ways to accomplish what you want. For most cases, this "pure" wrapper approach will do what you want.
Note that I didn't even have T extends Person. If the wrapper class doesn't need to use any Person methods, there's not much to gain from artificially restrict the generic. The call sites will all have the restriction either way. The one difference is that if a call site has a Wrapper<?>, then my code will only let you get the item as an Object, whereas the more restrictive T extends Person will let you get that item as a Person.
I hope I'm not missing something, but it appears to me that the wrapper pattern solves your problem:
public class Person implements IPerson{
String name;
int age;
public static void main(String[] args)
{
Teacher teacherWithID = new Teacher(new PersonWithID(new Person()));
Teacher teacherWithoutID = new Teacher(new Person());
}
}
interface IPerson{}
class Teacher implements IPerson{
public Teacher(IPerson personToBeWrapped){}
}
class Student implements IPerson{
public Student(IPerson personToBeWrapped){}
}
class PersonWithID implements IPerson{
public PersonWithID(IPerson personToBeWrapped){}
}
Whatever type your variable is should be the last wrapper.
The wrapper pattern can be considered to be a mechanic that allows you to "extend" classes at runtime. It's also called the decorator for that reason. You have competing inheritance mechanics in your code. (the built in one and the pattern) The result is that you cannot type your variable.
If you use the pattern exclusively, it works.

Trouble implementing the comparable interface

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.

Categories