Abstraction in Java? - 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).

Related

Trouble understanding An excerpt from 'Effective Java' about compareTo

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.

Does using super to elevate a variable to an abstract super class provide a benefit over assigning it in a subclass?

For starters, I hope I have worded the question well enough. If not, please feel free to edit it or suggest changes.
I'm working through a Java textbook to help with my university course and I came across an exercise asking me to create an abstract class Airplane, with three subclasses, B747, B757 and B767. Each object of those three subclasses has a unique serial number.
Cutting out a lot of the other parts of the question (which I hope aren't relevant!), I did this:
public abstract class Airplane {
String serialNumber;
public String toString() {
return getClass().getName() + ": " + serialNumber
}
}
I then declared three subclasses, each of which looked like this:
public class B747 extends Airplane {
B747(String serial) {
serialNumber = serial;
}
}
Finally, in my main program, I instantiated new objects using the following code:
Airplane a = new B747("ABC101");
System.out.println ("Airplane a: " + a);
Now, the code works fine. However, when I looked at the answers in the book, they chose to do it a different way. They instantiated each object in the same way, but instead in each class had the following method:
public B747 (String serial) {
super (serial);
}
In the abstract superclass Airplane, they then had:
public Airplane (String serial) {
this.serial = serial;
}
Was this just a matter of personal preference, to elevate the String to the superclass and act on it there, or does this provide any benefits, whether security or otherwise?
Was this just a matter of personal preference, to elevate the String to the superclass and act on it there, or does this provide any benefits, whether security or otherwise?
It's only changing where the variable is accessed - not where it's declared. And it's a good thing:
Every Aeroplane should have a serial number, so it makes sense for the Aeroplane class to enforce that
It allows the field to be private (and final) within Aeroplane, with a "getter" to provide read-only access to it as widely as is required
Both parts are important - but if you're not sure about the first aspect, consider what would happen if you had another few subclasses. Do you really want the assignment to occur in every single subclass? There will always be a superconstructor call - whether implicit or explicit - but there's no reason to repeat the assignment.
I definitely prefer the book's solution to your one - particularly if they make the field private and final. In my code, I hardly ever use non-private fields, other than for constants.
Also the super() is just a call to the superclass constructor(Aeroplane), it's common practice when making a class hierarchy as (far as I know) that you call upon the superclass constructor. There are keywrods like "this" and "super" which defines if it is values in the super/sub(child) class in the hierarchy. Java usually knows if you simply write the field value name, but it's actually in secret putting the "this" part in there for you.

Properly designing Java class hierarchies for code sharing and encapsulation

When laying out a class hierarchy, I often find myself frustrated at the gap between being able to encapsulate functionality while also sharing code. Part of the problem, of course, is lack of multiple inheritance, but interfaces help somewhat. The inability to define protected methods on interfaces seems to me to be the bigger issue.
The standard solution seems to be to have a public interface that is implemented by a protected abstract base class. The problem is when we have the following
public interface Foo {
public String getName();
}
abstract protected BaseFoo implements Foo {
abstract protected int getId();
private String name;
protected BaseFoo(String name) {
this.name = name;
}
#Override
public String getName() {
return this.name;
}
}
public class ConcreteFoo extends BaseFoo {
public ConcreteFoo (String name) {
super(name);
}
#Override
protected int getId() {
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
}
// in the foo package with the classes above
public class FooCollection {
private static Map<Integer, Foo> foos = new HashMap();
public static void add(Foo foo) {
synchronized(foos) {
foos.put(foo.getId(), foo); // can't call foo.getId()
}
}
}
// client code, not in the foo package
FooCollection.add(new ConcreteFoo("hello world"));
That is, we return one of our nicely-encapsulated objects to caller, but then any method which gets that object back needs to be able to rely on some internal functionality. That internal functionality cannot be part of the interface (that would break encapsulation), but to make it part of an abstract base class requires us to use casting.
We cannot make Foo an abstract class because other interfaces need to extend it to add optional, orthogonal functionality to a more complex hierarchy than is display here.
What are the standard approaches to this problem? Do you add getId to the Foo interface, even though clients shouldn't use it? Do you perform an unsafe cast to BaseFoo in FooCollection.add? If you check before casting, what do you do when the types don't match, even though they always should for all intents and purposes?
Any information you have on best practices in this sort of situation would be very helpful.
Edit: In case it's not clear, this example is intentionally oversimplified. The key point is that sometimes you return an "interface view" of an object. When that "interface view" is passed back in to a package-specific class, the method it is passed to will likely need to use internal functionality in its implementation. How does one manage that mismatch between internal and public functionality?
Okay, here's a couple of points:
Contrary to popular opinion, inheritance really isn't about sharing code. What you create in an inheritance hierarchy is an organization of things that share some common set of abstract behaviors; it just works out sometimes to have the effect of reusing some code.
The fashion has changed quite a bit in the last few years, so that deep and complicated inheritance hierarchies are no longer considered good form. In general in Java. you should
use aggregation before implementing an interface
use interfaces to express "mix-in" contracts
use inheritance only if the classes describe something that has natural inheritance.
If you really want the effect of multiple inheritance, build implementation classes for your interfaces, and aggregate them.
In particular, by defining your classes with interfaces and implementation classes, you make building tests much easier; if your interface is separate, it's almost trivial to build a mock for that interface.
I don't know about "best" practices, but here are a couple of ideas.
Interfaces are supposed to separate "what is to be done" from "how something is to be done". I don't think getters and setters belong in interfaces. I try to give them more meaningful signatures.
In your case, I see nothing wrong with two interfaces:
public interface Nameable {
String getName();
}
public interface Identifiable {
int getId();
}
Separate the two; force clients to implement only the ones they need. Your decision to make id part of the abstract class is arbitrary. Separating it out and making it explicit can be helpful.
Casting loses all benefit of polymorphism. I don't think that it should be abandoned lightly. If you must move getId() up to the interface, do so. If you can avoid it by different choices, do so.
"Best" depends on your context. Your simple example might not be true in all cases.

Confused with Java Encapsulation Concept

Good day!
I am reading a Java book about encapsulation and it mentioned the getter and setter method.
I've read that to hide the attributes, I must mark my instance variables as "PRIVATE" and make a "PUBLIC" method of getter and setter to access the data. So I tried making a similar but not the conventional code about it as follows:
public class AddressBookEntry {
private String name;
private String address;
private String telNo;
private String email;
public void getAllInfo() {
name = JOptionPane.showInputDialog("Enter Name: ");
address = JOptionPane.showInputDialog("Enter Address: ");
telNo = JOptionPane.showInputDialog("Enter Tel. No: ");
email = JOptionPane.showInputDialog("Enter Email Address: ");
}
}
Does my code above exposes my variables because I assigned it directly? How can I do this better? Would it be better if I make the conventional getter and setter method instead and assigned the values on the other class? What does "hiding the data" means?
Thank you.
You use setters and getters to make the variables accessible from outside your class. In your example you will have
public class AddressBookEntry {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
You will access the name property from a UI class (it isn't good to mix UI and business logic in the same class):
public class MyPane extends JFrame {
public getAllData() {
String name = JOptionPane.showInputDialog("Enter Name: ");
AddressBookEntry entry = new AddressBookEntry();
entry.setName(name);
// You can't use entry.name = name
}
}
Yes and no. The point of encapsulation is that it prevents other classes from needing to know what your class is doing behind the scenes. If you store your name in a String (as you've done here), read/write it from a file, or do something different, the point of encapsulation is that to the user of your class it doesn't matter because all they see is String getName( ) and void setName (String name).
Since the modification of the data is entirely under the control of your class here, it doesn't break encapsulation. If you did store name to file, then you could potentially do so in getAllInfo without any other user of the class being any the wiser. Since the observable behaviour from the outside of the class still hides what the internals of the class is doing, it's still encapsulated.
That said, this is a very unconventional approach. Like I describe in the first paragraph, use of accessor methods (getters and setters) is a more idiomatic approach, and easier to understand for someone else using your code. You can do what you do, it doesn't break encapsulation, but it's not what I'd call elegant or typical.
The idea of private class members (attributes, fields) is to access them directly inside the declaring class (not instance!) only. All other classes will have to use other accessors, for example getter and setter methods. So the way how the AdressBookEntry stores the name, address, telNo and email values, is perfectly hidden inside the class.
You don't have to use getters or setters, although, sometimes there are good reasons to do so inside the class too. Using getters and setters sometimes makes sense if you do some logging or validating before a value is set.
This doesn't violate encapsulation, as it doesn't expose the internal data to another class. You may wish to look at Model-View-Controller (MVC) though to help separate out your interface from your data.
Traditional you create a single getter and setter for each variable as needed like so:
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
Don't create getters for variables that won't need to be accessed outside of the class, and don't create setters for variables that won't need to be set outside of the class.
If following MVC and using the traditional getters and setters like above, you would have the view code elsewhere and call something like
myAddressBookEntry.setName(JOptionPane.showInputDialog("Enter Name: "));
I agree with all the great answers provided. I would like to add another great benefit about using encapsulation and is the fact that by hiding the data from its clients (just as the examples described above) you can guarantee how to set and get these instance variables making your class easier to maintain and test (i.e if you have many clients manipulating your objects variables you don't need to go class by class writing the new functionality, instead you just modify the getter and setter).
By making usage only of the objects setters and getters, the details of its implementation can be hidden from the outside world. This is a nice advantage so other objects attempting to interact with your class won't be able to break its functionality. This also increases the likelihood that a system will be implemented effectively.
I find the answers above already answering your question. But, I see another issue with your code, which is, a security and data integrity issue. You are filling your class member directly out of the user's input w/o any validations on it. For example, you'd probably want to check that the email address has an xyz#abc.com pattern. A malicious user might also provide a very long string in the input causing unexpected errors.

Requiring enums of extending classes

I would like to require classes that extend my abstract class A to provide an enumerated type. I don't need to constrain the type itself, I just want to ensure that they provide some enumerated type. For example, I have an abstract class Animal and I want to ensure that every Animal has a set of behaviors. I don't need to constrain these behaviors or create a master list in any way; I just want to ensure that all Animals return a list of symbolic behaviors.
Ideally, I would like to say:
public abstract class Animal {
public List<Enum> getBehaviors();
}
but this won't compile cleanly.
Any ideas? Would it be better to approach this via Generics?
Ok, I'm going to expand my comment a bit here.
If you want to have your getBehaviors() method return a list of behaviors for a particular animal, making the method signature declare that a List<Enum<?>> is returned does nothing to help you. A client who gets your List<Enum<?>> from that method isn't able to do anything useful with it (who knows what it is?). The restriction also doesn't do anything to help ensure that the type of objects the behaviors list contains are actually "behaviors", whatever that means to in the context of your application. They could be days of the week, months of the year or just about anything!
What I'm guessing is that you have some enums like DogBehavior (with constants like BARK, BITE, etc.) and you want to ensure that only such behaviors are allowed in the list. The fact that these behaviors are collected in enums is an implementation detail. What you should do is introduce a common interface that designates something as a Behavior. If there aren't any specific methods associated with a Behavior, it could just be a marker interface (that defines no methods). Otherwise, you might want it to have some methods, like such:
public interface Behavior {
public String getName();
public void doBehavior();
// etc.
}
You could then have some enums that implement this interface:
public enum DogBehavior implements Behavior {
BARK("Bark") {
public void doBehavior() {
// bark
}
},
// etc.
private final String name;
DogBehavior(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Then, 'Animal' might look like:
public abstract class Animal {
public abstract List<Behavior> getBehaviors();
}
Which makes a lot more sense to me.
I'm a bit confused - if you want to require all Animals to export a set of behaviors, then ideally your goal would be to be able to write something like this:
Animal a = /* .. create some subtype of Animal .. */
List</* ?? */> behaviors = a.getBehaviors();
The problem here is that if you want each Animal create its own enumerated type for behaviors, you have no unified way of talking about those behaviors unless you explicitly specify some type that represents them. In other words, you can't fill in the /* ?? */ above unless in the Animal interface you provide a type that all Animal behaviors should be related to.
One option would be to define a class like this one:
public final class Behavior {
private final String name;
public Behavior(String name) {
this.name = name;
}
public String getBehaviorName() {
return name;
}
/* ... etc. ... */
}
Then, you could have each Animal type define getBehaviors() so that it returns a list of Behavior objects. This gives you a type-safe framework for discussing behaviors, and potentially the ability to add more complex actions for each behavior.
2 things I see wrong.
First, you need to mark that method abstract. You didn't provide an implementation.
Second, the Enum should be parameterized if you don't want a warning. Enum<?> should be enough if you don't need to restrict the Enum further.
However, as others have noted, this probably is NOT what you want. An Enum of "behaviors" is useless to you. They have no functionality once returned from getBehaviors(). You could iterate through them and list them, but that's worth nothing more than a List<String>.
I would think that you want a List<Behavior> where Behavior is an interface that DOES something for you.
EDIT: ColinD above beat me to the punch on the same point.
public abstract class Animal {
public List<? extends Enum<?>> getBehaviors();
}

Categories

Resources