Trouble understanding An excerpt from 'Effective Java' about compareTo - java

This is about the compareTo contract that classes can implement.
there is no way to extend an instantiable class with a new value
component while preserving the compareTo contract, unless you are
willing to forgo the benefits of object-oriented abstraction. The same
workaround applies, too. If you want to add a value component to a
class that implements Comparable, don’t extend it; write an unrelated
class containing an instance of the first class. Then provide a “view”
method that returns this instance. This frees you to implement
whatever compareTo method you like on the second class, while allowing
its client to view an instance of the second class as an instance of
the first class when needed.
I have read Why can't I extend an instantiable class with a new value component while preserving the compareTo contract?. It helped answer one or two questions i had.But the below question still remains unanswered to me.
1) If i define the two classes as unrelated,i am free to implement the compareTo method as i want.Agree that.But how am i making the two classes have the is-a/parent-child relationship.Can someone explain whatever Joshua called the "view" method?

Can someone explain whatever Joshua called the "view" method?
I will continue Jon Skeet's simple example from the answer that you linked in your post:
// In Jon's code, Person derives from NamedThing
class NamedThing {
String name;
}
class Person extends NamedThing {
Date dateOfBirth;
}
"Providing a view" rather than "extending" would mean designing your class hierarchy like this:
class NamedThing {
String name;
}
class Person {
private NamedThing namedThing;
// Here is the view method
public NamedThing asNamedThing() {
return namedThing;
}
// Here is a convenience method for accessing name directly
public String getName() {
return namedThing.name;
}
Date dateOfBirth;
}
This frees you up to implement a new compareTo inside the Person, because there is no requirement to stay compatible with the superclass. If you need to view your person as a NamedThing, call asNamedThing() to get a view of the person reduced to a thing with a name.
Note that since this is not an is-a relationship, the asNamedThing is somewhat misleading: you get the named thing inside the person, not the person who happens to be a named thing. This limits the applicability of compareTo: for example, you cannot sort persons among other NamedThings.

Related

Generic Method with different argument but same return type

I have multiple methods which accept different types in arguments but have the same return type. I am planning to create a generic method but not sure of the implementation.
Method 1 :
private Details mapStudentDetails(final Student student) {
return Details.builder()
.line1(student.getLine1())
.line2(student.getLine2())
.postcode(student.getPostcode())
.country(student.getCountryCode())
.build();
}
UPDATED Method 2 :
private Details mapTeacherDetails(final Teacher teacher) {
return Details.builder()
.line1(teacher.getAddressLine1())
.line2(teacher.getAddressLine2())
.postcode(teacher.getZipCode())
.country(teacher.getCountryCode())
.build();
}
How can I implement a generic method for this usecase ?
private Details mapDetails ( T type) {
}
Firstly, because you are using the same methods (getLine1(), getLine2(), getPostcode()) it's obvious that they are unrelated to the responsibilities of these classes and must reside somewhere else.
As far as these concerns are connected to postal service and don't related to the idiosyncratic responsibilities of the classes Student and Teacher they have to be externalized.
Let's group the behavior related to the post inside the interface PostDetails (sorry for a clumsy name). And I want to emphasize that it's highly advisable to use an interface for this purpose, not an abstract class like Person. Tomorrow you may wish to be able to send letters to the organizations but it doesn't make much sense for a class Campany to extend the class Person. Inheritance creates a tight coupling and can be easily misused. If you have a choice between an interface and abstract class in the class design interface takes precedence.
Methods of the PostDetails could be abstract or default (which will probably make sense because the procedure of sending letters except for special cases must be the same).
public interface PostDetails {
String getLine1();
String getLine2();
String getPostcode();
String getCountryCode();
}
Both Student and Teacher classes must implement the contract defined by the PostDetails.
public class Student implements PostDetails {
// implementation for Student
}
public class Teacher implements PostDetails {
// implementation for Teacher
}
As far as method mapDetails() isn't bound to any class and meant to use only behavior defined in the PostDetails it can accept any implementation of this interface (Student, Teacher, Company, etc).
private Details mapDetails(PostDetails postDetails) {
}
Update
If there's a need for two different sets of behavior related to postal service then it clearly has to be two interfaces (even if now you have only two classes this decision can bring benefits afterward). And as a consequence, there must be two overloaded versions of the mapDetails() method that accept as parameter instances of these interfaces.

Why do we need abstract methods?

I have been studying abstract methods lately and I can't understand why do we need them?
I mean, after all, we are just overriding them. Do you know its just a declaration? Why do we need them?
Also, I tried understanding this from the internet and everywhere there's an explanation like imagine there's an abstract class human then there're its subclasses disabled and not disabled then the abstract function in human class walking() will contain different body or code. Now what I am saying is why don't we just create a function in the disabled and not disabled subclasses instead of overriding. Thus again back to the question in the first paragraph. Please explain it.
One of the most obvious uses of abstract methods is letting the abstract class call them from an implementation of other methods.
Here is an example:
class AbstractToy {
protected abstract String getName();
protected abstract String getSize();
public String getDescription() {
return "This is a really "+getSize()+" "+getName();
}
}
class ToyBear extends AbstractToy {
protected override String getName() { return "bear"; }
protected override String getSize() { return "big"; }
}
class ToyPenguin extends AbstractToy {
protected override String getName() { return "penguin"; }
protected override String getSize() { return "tiny"; }
}
Note how AbstractToy's implementation of getDescription is able to call getName and getSize, even though the definitions are in the subclasses. This is an instance of a well-known design pattern called Template Method.
The abstract method definition in a base type is a contract that guarantees that every concrete implementation of that type will have an implementation of that method.
Without it, the compiler wouldn't allow you to call that method on a reference of the base-type, because it couldn't guarantee that such a method will always be there.
So if you have
MyBaseClass x = getAnInstance();
x.doTheThing();
and MyBaseClass doesn't have a doTheThing method, then the compiler will tell you that it can't let you do that. By adding an abstract doTheThing method you guarantee that every concrete implementation that getAnInstance() can return has an implementation, which is good enough for the compiler, so it'll let you call that method.
Basically a more fundamental truth, that needs to be groked first is this:
You will have instances where the type of the variable is more general than the type of the value it holds. In simple cases you can just make the variable be the specific type:
MyDerivedClassA a = new MyDerivcedClassA();
In that case you could obviously call any method of MyDerivedClassA and wouldn't need any abstract methods in the base class.
But sometimes you want to do a thing with any MyBaseClass instance and you don't know what specific type it is:
public void doTheThingsForAll(Collection<? extends MyBaseClass> baseClassReferences) {
for (MyBaseClass myBaseReference : baseClassReferences) {
myBaseReference.doTheThing();
}
}
If your MyBaseClass didn't have the doTheThing abstract method, then the compiler wouldn't let you do that.
To continue with your example, at some point you might have a List of humans, and you don't really care whether they are disabled or not, all you care about is that you want to call the walking() method on them. In order to do that, the Human class needs to define a walking() method. However, you might not know how to implement that without knowing whether the human is or isn't disabled. So you leave the implementation to the inheriting classes.
There are some examples of how you'd use this in the other answers, so let me give some explanation of why you might do this.
First, one common rule of Object Oriented Design is that you should, in general, try to program to interfaces rather than specific implementations. This tends to improve the program's flexibility and maintainability if you need to change some behavior later. For example, in one program I wrote, we were writing data to CSV files. We later decided to switch to writing to Excel files instead. Programming to interfaces (rather than a specific implementation) made it a lot easier for us to make this change because we could just "drop in" a new class to write to Excel files in place of the class to write to CSV files.
You probably haven't studied this yet, but this is actually important for certain design patterns. A few notable examples of where this is potentially helpful are the Factory Pattern, the Strategy Pattern, and the State Pattern.
For context, a Design Pattern is a standard way of describing and documenting a solution to a known problem. If, for example, someone says "you should use the strategy pattern to solve this problem," this makes the general idea of how you should approach the problem clear.
Because sometimes we need a method that should behave differently in its instances.
For example, imagine a class Animal which contains a method Shout.
We are going to have different instances of this Animal class but we need to implement the method differently in some cases like below:
class Animal:
/**
different properties and methods
which are shared between all animals here
*/
...
method shout():
pass
class Dog extends Animal:
method shout():
makeDogVoice()
class Cat extends Animal:
method shout():
makeCatVoice()
dog = new Animal
cat = new Animal
dog.shout()
cat.shout()
So dog shouts like dogs, and cat shouts like cats! Without implementing the shared behaviors twice
There is a different behavior of shouting in these instances. So we need abstract classes.
Suppose you don't know about implementation and still want to declare a method then we can do that with the help of abstract modifier and making it an abstract method. For abstract method only declaration is available but not the implementation. Hence they should end with ;
Example:
public abstract void m1(); // this is correct
public abstract void m1(){ ... } // this is wrong
Advantage: By declaring abstract method in parent class we can provide guideline to child classes such that which methods are compulsory to implement.
Example:
abstract class Vehicle{
abstract int getNoOfWheels();
}
Class Bus extends Car{
public int getNoOfWheels(){
return 4;
}
}
If you want the short answer, think of this:
You have an abstract class Car.
You implement 2 classes that extend it, Ferrari and Mercedes.
Now:
What if you did one of the following, for the method drive(), common to all cars:
1) changed the visibility of the method,
2) changed the name of the method from driving to Driving,
3) changed the return type, from a boolean to an int
Think about it. It might not seem to make any difference right, because they are different implementations?
Wrong!
If I am iterating through an array of cars, I would have to call a different method for each type of car, thereby making this implementation of abstract useless.
Abstract classes are there to group classes with a common template, that share common properties. One way this helps would be the looping over the array:
Abstract methods ensure that all cars declare the same method,
and therefore, any object of a subclass of Car will have the method drive(), as defined in the abstract class, making the for loop mentioned easy to implement.
Hope this helps.

How can a child interface reuse its parents' implementations?

Recently I had an interview and I was asked the following question. Given the following class/interface structure:
Question:
How can one implement interface EmployedStudent to reuse code from StudentImpl and EmployeeImpl.
I suggested to compose Employee and Student into my implementation.
Based on the interviewer's reaction I don't think they found it to be the best solution. I spent a lot of time thinking about it but I cannot come up with another solution.
Create a class that implements both Employee and Student. In your class, create an instance of both EmployeeImpl and StudentImpl. Make your class delegate all method calls to either one of the objects then.
public class EmployedStudent implements Employee, Student {
private EmployeeImpl employee = new EmployeeImpl();
private StudentImpl student = new StudentImpl();
public int getSalary() {
return this.employee.getSalary();
}
public float getAverageGrade() {
return this.student.getAverageGrade();
}
}
So, you could have implements Employee, Student internally delegating to both EmployeeImpl and StudentImpl, but also inherit from one implementation class.
Now the class name EmployedStudent (not StudyingEmployee or BothEmployeeAndStudent) suggests:
class EmployedStudent extends StudentImpl implements Employee {
Employee asEmployee = new EmployeeImpl();
Yeah, a tiny bit more efficient as only delegating to one other class.
The use-case is however far from realistic: all kind of combinations are thinkable of several classes. In that case your solution is more universal. Really universal, is a lookup-mechanism:
public class Person {
public <T> T as(Class<T> klazz) { ... }
}
Person person = ...;
Student asStudent = person.as(Student.class);
if (asStudent != null) {
...
}
Employee asEmployee = person.as(Employee.class);
if (asEmployee != null) {
asEmployee.quitJob();
asEmployee = person.as(Employee.class); // null
}
That is a lookup of capabilities. It typically can replace a cumbersome inheritance hierarchy, say of Vehicle, RoadVehicle, SwimmingVehicle (boat), FlyingVehicle (air plane), WaterAirplane (?), AmphibianTank (?) by using capabilities Swimming, Flying, Driving.
The difference is the entire decoupling.
As java doesn't support multiple inheritance, you could/should
either have a field for each of the wanted superclasses
or derive from one superclass and have a field for the other one.
The fields are then referred to by "our" implementation of the respective methods.
This is one of the design patterns from the GoF, I think it is the Proxy pattern.
With Java 8, you can move code into the interface itself. That solves the "multiple inheritance" problem.
While the Interface Segregation Principle can sometimes be helpful, and some people scoff at the idea of interfaces which don't promise that all implementations will support all members, I would suggest that it may be helpful to have Student and Employee interfaces which include isStudent and isEmployee members, and then have Person implement both interfaces; some methods like giveRaise() shouldn't work on someone who isn't an employee, but others like getOutstandingPay() should work just fine (if someone hasn't earned any money, the method should simply return zero).
While it may seem ugly to complicate all Person objects with methods that won't be applicable for many of them, such a design avoids difficulties in the event that a student gets hired, or an employee starts taking classes. Having separate classes for Student, Employee, and StudentEmployee, even if one could do so easily, would require that a Student who got a job be replaced with a new object instance in order to become a StudentEmployee. By contrast, if one has a Person class whose instances may or may not be able to handle methods like giveRaise, then one can handle situations where objects' abilities change during their lifetimes.

Why can't I extend an instantiable class with a new value component while preserving the compareTo contract?

Per Effective Java by Joshua Blotch:
There is no way to extend an instantiable class with a new value
component while preserving the compareTo contract, unless you are
willing to forgo the benefits of object-oriented abstraction
Can you please explain the above with examples and the challenges? Can you also explain what Joshua means by "Value Component" and what other types of components are available.
This frees you to implement whatever compareTo method you like on the
second class, while allowing its client to view an instance of the
second class as an instance of the first class when needed.
Can you also explain what Joshua means by second class as an instance of the first class?
Can you please explain the above with examples and the challenges?
Sure. Consider two classes like this - I've left out all the getters, setters etc, but hopefully you get the drift:
class NamedThing {
String name;
}
class Person extends NamedThing {
Date dateOfBirth;
}
Ignore whether this is a good example of inheritance - it's a simple one.
It would be natural for NamedThing to implement a comparison based on name, in alphabetical order.
It would also be natural for Person to implement a comparison which first compares the name (so stays consistent in that respect) but then also checks for one date of birth being earlier than another.
Now imagine this:
NamedThing person1 = new Person("Jon", date1);
NamedThing person2 = new Person("Jon", date2);
NamedThing thing = new NamedThing("Jon");
int comparison1 = person1.compareTo(thing);
int comparison2 = person2.compareTo(thing);
int comparison3 = person1.compareTo(person2);
int comparison4 = thing.compareTo(person1);
What would you want all these results to be? If Person.compareTo was smart enough to only apply its date processing to instances of Person, then you might expect comparison1 and comparison2 to be 0, but comparison3 to be non-zero.
Presumably comparison4 would have to be 0, as it's using NamedThing.compareTo, which only compares names.
Fundamentally, there's a problem trying to compare instances of different types. It ends up being cleaner to have an external definition of a comparison, which defines what comparison it will use. You could thus have a Comparator<Person> which only accepted Person references and used both name and date, and a Comparator<NamedThing> which only compared by name. The behaviour would have symmetry and clarity.
Can you also explain what Joshua means by second class as an instance of the first class?
You've taken it out of context. It's: "view an instance of the second class as an instance of the first class" - e.g.
// First class = Animal
// Second class = Zebra
Animal person = new Zebra();
This means for each subclass you have to override compareTo method.
Casting to the superclass is called upcasting.

Abstraction in Java?

Today i heard from my friend, that encapsulation is not only achieving information hiding but also abstraction. How does it achieve?
public class employee {
private String name;
private int id;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
The above example achieves encapsulation where i am allowing the class to access my public method rather than private members, but where does the abstraction come into picture here? Can anyone explain me on abstraction in a bit clear manner.
There's two different things, information hiding and abstraction.
Information hiding makes abstraction possible, but it is something different. For example, using your code
public class employee {
private String name;
private int id;
public void setName(String name) {
this.name = name;
}
public String getName(){
return name;
}
}
The id field is actually hidden. This allows one to handle ids in a manner that is decoupled from the rest of the program. Your name field is actually hidden too, as you don't access the name field directly, but the code in getName and setName does.
Once you hide the structure of the data from the rest of the code, forcing access through methods, it is possible to create a number of replaceable implementations of an item. For example, an employee is a conceptual kind of person, so you could rewrite the above like so:
public interface Person {
public abstract String getName();
}
public class Employee implements Person {
private String name;
private int id;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
Now your code can deal with the Employee as a Person. After rewriting the rest of the code that doesn't explicitly deal with Employees to deal with Persons, you could implement other kinds of Persons and leverage the non-Employee specific tasks that are now Person tasks.
public Customer implements Person {
private String name;
private integer moneySpent;
public String getName() {
return name;
}
}
So a person searching routine, as long as it only indexes Person objects can now include searches of both Employees and Customers. This is because the code dealing with Person objects is actually dealing with a higher level abstraction that both Employee and Customer objects share.
When dealing with Objects on an abstract level, the names of the methods are shared across the abstraction; but, the actual code executed depends on the unmentioned underlying type of the object. In other words, if you ask a Person (who happens to be an employee) getName() then it will respond with the Employee.getName() function, while a Customer will respond with a Customer.getName() function. Since the code calling getName() is operating on Persons it has no idea which type of person it will be handling, but the apparent change in behavior (the selection of the right block of code on a per-object basis) still happens. This phenomena is known as Polymorphisim, and if you are first hitting these concepts, you'll hear Polymorphisim as a word used a lot.
An example of polymorpic behavior:
public interface Animal {
public abstract String makeSound();
}
public class Cow implements Animal {
public String makeSound() {
return "Moo Moo!";
}
}
public class Dog implements Animal {
public String makeSound() {
return "Ruff Ruff!";
}
}
public class Sheep implements Animal {
public String makeSound() {
return "Baa Baa!";
}
}
// this class demonstrates the polymorphic behavior
public class Farm {
public static void main(String[] args) {
ArrayList<Animal> animals = new ArrayList<Animal>();
animals.add(new Cow());
animals.add(new Sheep());
animals.add(new Dog());
for (Animal animal : animals) {
// this is where the polymorphisim occurs
// each animal will make a different sound
// because the makeSound method is getting
// bound to different blocks of code based
// on the exact type of animal class hiding
// under the Animal abstraction.
System.out.println(animal.makeSound());
}
}
}
expected output:
Moo Moo!
Baa Baa!
Ruff Ruff!
even though we never explicitly changed classes, and we never explicitly changed methods. It was the binding of the abstract method to the explicit subclass that was changing, which is something that only happens in systems that support polymorphisim.
# John your friend is right by implementing the encapsulation you also achieve abstraction.
public class employee {
private String name;
private int id;
public void setName(String name){
name= name+"something that you want to edit";
this.name = name; }
public String getName(){
return name; }
}
in this way you have edited ur set method and hided the details from the user which is nothing but abstraction...
thus by writting getters and setters you hide user to do the unneccessary task...
public void setName(String name){
/*some internal logic suppose in database you want name
*should be added with its id but what user to do with it.*/
this.name = name; }
public String getName(){
/* now suppose you have recieved the name from
*data base it has id but you want user to know only
name then you will write the logic here to show the name.*/
return name; }
I know adding id to name is a stupid example but thats what i can think of right now... but consider for a very big project you many times write code in set(or call other method which modifies the parameters of it) then what...
suppose you get the name but you want to save it in a encrypted form in db, then what.
User dont care about the encryption but yes you have to... because its uneccesary to the user but important to you. So that should be in the code of yours but hidden from the user and thats what is all about abstraction*("HIDING THE UNNECCESARY DETAILS FROM USER")*
EDITED:-Go to the source! Grady Booch says (in Object Oriented Analysis and Design, page 49, second edition):
"Abstraction and encapsulation are complementary concepts: abstraction focuses on the observable behavior of an object... encapsulation focuses upon the implementation that gives rise to this behavior... encapsulation is most often achieved through information hiding, which is the process of hiding all of the secrets of object that do not contribute to its essential characteristics."
from above you can conclude the same
I think he's confusing polymorphism with encapsulation. Polymorphism can help you achieve abstration.
It's mostly encapsulation here, but there is some abstraction as well. By using a method called setName(), code that consumes your class doesn't need to know how you're implementing the operation of "setting a name". For all they know, you're calling out to a webservice and setting it in a database somewhere. Or maybe you're ignoring the parameter entirely and setting the name to "Steven" every time. Those facts are abstracted away from the caller.
I don't think you can prove encapsulation with that particular example. It's more like this:
interface NameService {
String getName();
}
Now, tell me: does a class implementing this interface get the name from a flat file, a database, a nosql store, or someplace else?
Abstraction is all about a concept/model which cannot be realized / instantiated as such.
Abstraction is all about restriction on an object's method/members behaviour to other classes.
Personally I wouldn't say encapsulation is really about abstraction (though I see how it could be taken that way), it's about only permitting a user to see or do what's necessary - they only see an interface to the class, not its inner workings. In your case it's achieved because you're only ever setting or getting the name of the particular class, you never access the name variable directly and never see how it's stored. So you could change the name or type of the name variable to something completely different and the interface to your class would still work and look the same. I guess that could be taken in a sense as an abstraction.
The definitions are loose, but I'd consider polymorphism to fall more into the realms of abstraction, where you decouple the implementation (say, ArrayList) from the interface it inherits (say, List.) That way you just deal with the list interface, and the underlying list could be anything, but that's an implementation detail and because you're an abstract level "above" it, you don't need to worry about it. Of course this is a simplification, sometimes you need to know implementation details for performance reasons or if some operations may not be implemented or allowed on your specific implementation. But from a loose viewpoint (and a pure OO viewpoint) it holds.
Whatever you understand it to be, the most important thing is you understand the logic behind it, why it's a good idea and why it's always better to do things that way (in this case, have fields as private and use getters / setters to access them.)
but where does the abstraction come into picture here?
you've said it yourself: "allowing the class to access my public method rather than private members"
or in other words: allowing other classes to access what they may access, and protecting what they may not.
the abstraction here comes from the public methods, for instance in getName() you don't need to always give the private member value, it could be appended with other value or even it could give totally different thing. it's like saying: "tell me your name, regardless how you'd give it to me". maybe a better example would be a method named getYourWorkDone(). the principle remains the same: "get your work done! how? I don't care how!"
the encapsulation part is from the private members. this class encapsulates those private members so they are grouped to form the class' state.
java official documentation for you to understand when to use interface or abstraction.
Also, I couldn't help notice that you were confused between encapsulation and abstraction so here is a simple difference between them for geekforgeeks website
Encapsulation is data hiding (information hiding) while,
Abstraction is detailed hiding
(implementation hiding).
Encapsulation groups together data and methods that act upon the data, data abstraction deal with exposing the interface to the user and hiding the details of implementation.
It seems encapsulation and abstraction has got everyone confused. If you ask me, those are poles-apart topics and there is absolutely no scope of confusion in this.
abstraction happens when you use "abstract" keyword, and encapsulation happens when you create a class. a good implementation of encapsulation involves making all your data members private.
I wrote a few blog posts that might help you:
Learn how to use an Abstract Class in Object Oriented Design
The Theory of Abstraction
Abstraction is done when you want to hide the data.Whereas encapsulation is done when you want to hide both data and code.That is wrapping both data and code which you implement.
You can implement abstraction by using abstract class or interface.
In abstract class we can either write concrete methods or abstract methods but in interface we can only use abstract methods.
You can implement encapsulation by using access modifiers like public, protected, private.
These access modifiers control the access of your data i.e whether it should be public(can be seen by anyone) or protected(can be accessed only by extended classes) or private(hiding it from everyone).

Categories

Resources