if we have 2 class Zoo & Moo as follows:
public class zoo {
String superString="super";
private String coolMethod(){
return "Zoo method";
}
}
public class Moo extends zoo{
public void useMyCoolMethod(){
zoo z=new zoo();
System.out.println(superString);//1
System.out.println(z.superString);//2
}
public static void main(String[]args){
new Moo().useMyCoolMethod();
}
}
at 1 & 2 we print the value of the String in the super class through inheritance and access, the question is , what is the benefit of Access although i can do the same thing by inheritance ? knowing that the Access approach isn't allowed if the two classes is in diff packages
By accessing through the object ref you are modifying the referenced object's state, by inheritance you are modifying the object you are currently in ( this reference ). So there is actually no benefit aside from encapsulation at class level and package level through out the access modifiers and that sort of thing, you just use it depending on the behavior you want for you're code, or in this case, how restrictive to modify the state of objects depending on the context.
But aside from that, i'm not sure if there is anything else.
Regarding your example there is no benefit at all in "access" the method, if you really wants to print "super" twice.
But normally OO programs contains more than two classes and the authors tries to modularize the code with defined interfaces (aka public methods or an API). Create modules with inheritance only is very hard and create clumsy code. So objects will need other instances and call there method by "access".
In line 1, you are using inheritance, i.e. you have a class animal and you have method move() which moves the animal using his four leg. But in case of Kangaroo, you want to use most of the feature of animal class but want to change how it moves based on the fact that it jumps and uses it hind leg for movement.
In Line 2, you are using composition, i.e. when you want to create car, you will need different component and they will interact with each other for that car to function. Here you can not inherit from GearBox or Engine but you have to use them as part of Car (or what you are calling access).
In the end its the relationship between Zoo and Moo will decide what method you want to use
Using this access and inheritance is same when you do Not want to modify the content of the inherited memeber..
eg:
public class A {
String s = "Hello";
}
public class B extends A{
String s = "Hi;
System.out.println(s); // Will print the s in class B
System.out.println(new A().s); // Will print the s in class A
}
Now as String s has no modifier, it is considered having Default modifier, that means it can be accessed by classes only with in its own package.
If you use protected access modifier, then you Need to extend the class and then use the inherited members, but you can Not use the protected member by creating an instance of the class that holds it and then use dot operator to access it, this will Not work..
eg :
package com.go;
public class A {
protected String s= "Hi";
}
package com.fo;
public class B extends A {
System.out.println(s); // This will work
A a = new A();
System.out.println(a.s); // This will NOT work
}
The access (default or package-private) would be useful if Moo was in the same package an didn't extend Zoo.
First of all, I think is a good practice to maintain class attributes with private visibility, and access them through getters and setters. In second place, you are not accessing the attribute by inheritance, you are creating an instance of Zoo, and accessing the superString attribute because of it package visibility, you could also access them from another class of the package that don't even extends Zoo class (and that's generally not a good thing) In third place, you don't need to create an instance of the super class to access his public or default attribute, you could simply do:
System.out.println(this.superString)
wich is absolutly the same as (if not local variable or parameter declared with the same name):
System.out.println(superString)
In conclusion, having default or public attributes, let client classes access them (read and write) without the class could do nothing about it, and this could bring side effects for the methods of the class that use those attributes.
Example 2 you have a separate instance of your zoo object, which is a bit weird, but since the method will always return the same thing there isn't much difference. If you changed your method to be based on constructor input or something you could see a difference in the 2.
public class zoo {
public String superString;
public zoo (String _superstring) {
superString = _superstring;
}
}
public class Moo extends zoo{
public void useMyCoolMethod(){
zoo z=new zoo("string1");
System.out.println(superString);//1
System.out.println(z.superString);//2
}
public Moo (String _superstring) {
superString = _superstring;
}
public static void main(String[]args){
new Moo("string2").useMyCoolMethod();
}
}
Will return
string2
string1
Related
I'm trying to understand the concept of abstraction in java. When I came through some tutorials they said that Abstraction is a process where you show only “relevant” data and “hide” unnecessary details of an object from the user.
This is a simple example of how abstract classes are working.
public class Demo {
public static void main(String[] args) {
Animal a = new Dog();
a.sound();
}
}
abstract class Animal {
abstract void sound();
}
class Dog extends Animal {
#Override
public void sound() {
System.out.println("woof");
}
}
I understand that though abstract classes we can implement common methods in sub classes like sound() method.
What I don't understand is how that help with data hiding and viewing necessary data only.
Please explain this concept to me.
If you have good example please include that too.
In your example, you create a Dog and then use it as an animal. In this case, the abstraction is not very useful, because you know that the variable a always refers to a dog.
Now let's say that in some other class you have a method soundTwice:
class OutsideWorld {
static void soundTwice(Animal a) {
a.sound();
a.sound();
}
}
Here you don't know what kind of Animal a refers to, but you can still sound twice.
UPDATE
I'm adding this class because the class Demo doesn't hide much: it needs to know about class Dog because it creates an instance of it. class OutsideWorld on the other hand doesn't: it only knows about class Animal and what class Animal exposes. It doesn't even know that class Dog exists.
we can now write a class Cat with a different implementation of method sound ("meow"), and we can still use the same soundTwice method with a Cat.
We could then rewrite the Demo class:
public class Demo {
public static void main(String[] args) {
Animal a = new Dog();
OutsideWorld.soundTwice(a);
a = new Cat();
OutsideWorld.soundTwice(a);
}
}
That would, of course, produce the output:
woof
woof
meow
meow
Abstraction in Java is not different then what we use in Software engineering terms.
Abstraction generally answers to WHAT part of your problem statement.
What all operations a system will support?
What is the system meant for?
Think about the abstract datatypes:
Example Stack
All you care about is
pop() --> return you the top element
push() --> adds the element
You simply don't care about the implementation details. So your java classes are abstracted in the same way.
Abstraction is not just about showing only “relevant” data and “hide” unnecessary details of an object from the user.
Data Abstraction is the property by virtue of which only the essential details are displayed to the user.The trivial or the non-essentials units are not displayed to the user. Ex: A car is viewed as a car rather than its individual components.
In java, abstraction is achieved by interfaces and abstract classes. We can achieve 100% abstraction using interfaces.
The one you are explaining in your example is one just form of it.
In your example of Animal class, if sound() method is not an abstract one and you have some random abstract method in that class, imagine a case someone wrote the Animal class and you are extending it in Dog class. Irrespective of the implementation in Actual Animal class, you can write the code in your current class.
Imagine the you haven't overriden the sound() method in Dog class, still if you call `
Dog d= new Dog(); d.sound();
` will get you the code of Animal sound().[Given: sound() method is not abstract]. The code of Animal class would be executed. Dog object does not even know what the sound() method has in it...but it is still able to make use of it. This process of not knowing but making use of something is what abstraction actually is
As mentioned by Yati Sawhney, pop() and push() methods are quite good examples.
Else,
you can have hascode() and equals() method from Object class,
where no one knows how the calculation is done but you end up with a
number and comparing the references respectively.
Data Hiding/Encapsulation:
Data hiding is not same as Abstraction. Not to confuse one with the other.
Abstraction is hiding the code implementation from other Object/user
whereas Data hiding is achieved by Encapsulation via POJO classes.
Data hiding has to do with the instance variables which decides the
state of the Object. Hiding its content using the setter() and
Getter() methods is Data Hiding/ Encapsulation.
You may wonder, how a getter() method is hiding the data whereas it just returns the data we requested but there is an untold story about the getter/setter methods.
Example: Refer the getName() method from the below code
public class Person {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
// can restrict the code without displaying data to user
if(condition)//restricted user check
return null;//returning null because the user is not supposed to view the data
return name;
}
}
Abstraction means - not providing/having the implementation details. Imagine you are the authority to decide on what parts a Car must have. You will list those functionalities as abstract methods.
Later you will share this (contract) abstract template to Hundai, Ford etc to have their own implementation to make a complete Car.
Abstraction
Ways to achieve Abstraction
There are two ways to achieve abstraction in java
Abstract class (0 to 100%)
Interface (100%)
Basic Knowledge about :
Abstract Methods and Classes
An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed.
public abstract class ClassName{
// declare fields
// declare nonabstract methods
abstract void methodName();
}
When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class. However, if it does not, then the subclass must also be declared abstract.
An abstract method is a method that is declared without an implementation (without braces, and followed by a semicolon), like this:
abstract void methodName(Parameter List);
Abstraction is a process of hiding the implementation details and showing only functionality to the user.
Understanding the real scenario of abstract class:
Consider a situation of making a function to get student strength of any school.
Now we will create an abstract class and abstract function getStrength().
Then every school (Govt or private) can use this abstract method and provide implementation.
//Consider this Code
package stackoverflow;
abstract class StudentStrength {
abstract int getStrength();
}
class GovtSchool extends StudentStrength {
#Override
int getStrength() {
return 100;
}
}
class PrivateSchool extends StudentStrength {
#Override
int getStrength() {
return 200;
}
}
public class GetInfo {
public static void main(String args[]) {
StudentStrength ss;
// referring abstract class and creating object of child class
ss = new GovtSchool();
System.out.println("Student strength in Govt School : "+ ss.getStrength());
// output of above : 100
ss = new PrivateSchool();
System.out.println("Student strength in Private School : "+ ss.getStrength());
// output of above : 200
}
}
Explanation:
In this example, StudentStrength is the abstract class, its implementation is provided by the GovtSchool and PrivateSchool classes.
Mostly, we don't know about the implementation class (i.e. hidden to the end user) and object of the implementation class is provided by the factory method.
In this example, if you create the instance of GovtSchool class, getStrength() method of GovtSchool class will be invoked.
File: GetInfo.java
Student strength in Govt School : 100
Student strength in Private School : 200
ANSWER TO:
What I don't understand is how that help with data hiding and viewing necessary data only.
Like demonstrated in the above code, we are referring the abstract class and using the functionality of the child class hiding the working of child class from the end user.
I hope I was helpful :)
This is probably answered somewhere, but I have no idea what to search for. Imagine you have the following...
The superclass, Animal.java
public class Animal {
public String noise = "squeak";
public String toString() { return noise; }
}
The subclass, Lion.java
public class Lion extends Animal {
public String noise = "ROAR!!";
public String toString() { return noise; }
}
The main class, Runner.java
public class Runner {
public static void main(String[] args) {
Animal a = new Animal();
System.out.println(a);
System.out.println(a.noise);
Lion b = new Lion();
System.out.println(b);
System.out.println(b.noise);
Animal c = new Lion();
System.out.println(c);
System.out.println(c.noise);
}
}
The output is:
squeak
squeak
ROAR!!
ROAR!!
ROAR!!
squeak
Why does c.noise return squeak? What is the difference between instance method invocation and instance variables that one returns what you'd expect, and the other does not? Why does Java do this?
Thanks
Short answer:
You can override methods, but it's not possible to override fields.
Long answer:
Each class sees the methods and fields of it's own and of it's parents (except for private methods). If the child delcares a method, whose name is the same, as the name of the method in his parent class, this method becomes overridden - if this method is somehow invoked on the child instance (even from the one of the parent's methods), the brand new method will be used instead of the parent's one. Child may still call the original method of his last parent via super.method(...) call.
But the story is different when we come to the fields. If the child declares a new field, that is named exactly as the field in parent class, it will simply hide the parent's field without overriding, just like the local variable hides global one. So the child methods will simply see the child's fields, but the parent's method will continue to see parent's field, and child's field will not be visible by any means from the parent class - that's what you've got.
Child can access the field of it's parent via ((Parent)this).field.
Longer answer:
So really the way you'd do this is define Lion thus:
public class Lion extends Animal {
public Lion() {
noise = "ROAR!!";
}
}
So now for Lion instances the noise member variable of Animal has been updated to ROAR!!
Of course you'd (almost) never actually have a public mutable member on a class like that in the wild.
You can not override fields, new declaration of noise in Lion hides parent's noise attribute. do like this:
public class Lion extends Animal {
// public String noise = "ROAR!!"; // <---- Remove this line
public Lion() {
noise = "ROAR";
}
public String toString() {
return noise;
}
}
All non-static methods in java are by default "virtual functions". Unless they're marked as final (which makes the method not overridable). Java uses a virtual method table to call the correct object's method.
This is because Java talks only about method overriding. Member variables can only be shadowed in child class. So when you say c.noise it actually refers to the string variable in parent class as the c if reference type Animal.
The topics you are interested in are Dynamic Dispatch and Virtual Method Table. Basically, by design, Java allows for methods to be overridden (assuming they are non-final) and at run time the JVM will execute the appropriate implementation. This polymorphic attribute is only afforded to methods. Good OO design would dictate the fields be encapsulated anyway.
Why is this valid?
Foo.java
public class Foo {
public Bar getBar() {
return new Bar();
}
private class Bar {}
}
If Bar is private, how will users of this class use this method? Polymorphism can be used of course, but shouldn't this be invalid and the declaration should indicate this as returning an Object?
I've just been doing a bit of research on this and have not been able to find a definitive answer. It seems most likely that it is just an oversight on the part of the Java language designers and since it doesn't actually do any harm it has been left. It's no different really from putting a public method into a private class. Nothing stops you doing this, even though there is no way to actually access that public method.
Certainly NetBeans gives you the warning "Exporting non-public type through public API" when you try to do this. I expect most other environments will give a similar warning.
The returned object is entirely useless to anyone who tries to use it (unless they use reflection), pretty much all they can do is store it into an Object (or any other super class that they do have access to) and then pass that Object around.
You could potentially want to do this if the passed Object is being used as a "handle" that gets passed around but never operated on. In that case though it would still make much more sense to have the class public but make all the methods within it private to prevent them being acted on outside your class (or define a public interface to return and have the private class implement that).
So the answer seems to be:
It probably shouldn't be valid, but as it doesn't do any harm it has never been blocked.
There is a good answer here on a similar subject:
Exporting non-public type through public API
Why is this valid?
Because client code in the call place might be expecting an Object(or not expecting anything at all), there is no problem with calling this method from anywhere:
Object o = new Foo().getBar();
It is valid because Bar is visible to the Foo class. Thus it compiles.
Of course another class can not see Bar and thus can not use the return value.
But another class can still just invoke the method without using the return value.
public class FooBar {
public void invokeBar() {
Foo foo = new Foo();
foo.getBar();
}
}
A public method returning a private class can be useful it you need to be able to call the method from any scope (e.g. to mutate an internal state of Foo), and for internal usage if you need any kind of result in addition of simply calling the method.
public class Foo {
private String myString;
public String getMyString() {
return myString;
}
}
This is valid as well. Why should inner classes behave differently?
Making Bar private only makes it invisible to the outside world just as making fields private.
One important caveat is that even if you are able to call getBar() on a Foo object you can't call methods of that reference (because of the visibility).
So the main thing is that you can do that but you should not do so.
The only situation I can imagine is when Foo is also an inner class and the outer class of Foo wants to use Bar.
Inner class
Inner classes represent a special type of relationship that is it can access all the members (data members and methods) of outer class including private. Nested classes can lead to more readable and maintainable code because it logically group classes in one place only.
It is one of the form of nested types. This kind of class declaration is known as inner class. If you declare the inner class as static, then it would be known as top-level nested class. Other forms of nested types available in Java are local class; class declared and defined within a block,ie, a method or a constructor or an initializer block. The fourth form of nested type is anonymous class; a class without any name whose object is used where the class is defined.
As far as your case is considered, i.e., inner class all the classes within a class can be declared with public, private and protected access specifiers. All the classes with in the enclosing class as well as enclosing class itself share a trust relationship. That means, all the private members of inner class as well as private members of enclosing class is shared among each other. However you cannot access the object of inner class without an object of enclosing class.
When you will try to create an object of inner class compiler would report a compile-time error. However following example access the private members of each other class, i.e., enclosing class access private members of inner class and inner class access private members of enclosing class :
class Bar {
private static int x;
public void getFoo() {
System.out.println(new Foo().y);
}
private class Foo {
private int y;
public void getBar() {
System.out.println(Bar.x);
}
}
}
public class Test{
public static void main(String[] a) {
Bar b = new Bar();
//Bar.Foo f = new Bar.Foo(); This is completely illegal syntax.
}
}
Best example you could have for an inner class is the relationship of an Accounts class which is enclosing class and Transaction class which is inner class. One Accounts class can have more than one Transaction objects but Transaction object cannot exist without Accounts object.
Albeit, returning an object of private inner class is useless as it becomes invisible outside its class. As the above example of Accounts and Transaction class explains. Transaction cannot exists without Accounts object.
I have a perfectly valid use case for this, and I'm glad this is allowed.
Let's stay you have a class that creates UI pieces. It accepts somekind of domain object and creates a piece of UI:
public Node createPersonUI(Person person) {
BasePanel panel = new BasePanel();
// ... setup panel with values ...
return panel;
}
BasePanel is a subclass of Node and is some internal class that the caller has no business with, as this class determines how things will look.
Now, I found myself needing to re-use part of this class when I needed to support a new object, PersonalProfile that contains much more information, but also contains the basic Person data:
public Node createPersonalProfileUI(PersonalProfile profile) {
BasePanel panel = new BasePanel();
// ... setup panel with values ...
return panel;
}
However, that code was partially duplicated, so I did:
public Node createPersonalProfileUI(PersonalProfile profile) {
BasePanel panel = (BasePanel)createPerson(profile.getPerson());
// ... only setup missing values ...
return panel;
}
The cast however is a bit ridiculous -- changing it to return BasePanel not only works, but doesn't expose any functionality of my private class. Instead it only exposes the methods from any public classes it inherits from... brilliant!
Full code:
public BasePanel createPersonUI(Person person) {
BasePanel panel = new BasePanel();
// ... setup panel with values ...
return panel;
}
public BasePanel createPersonalProfileUI(PersonalProfile profile) {
BasePanel panel = createPerson(profile.getPerson());
// ... only setup missing values ...
return panel;
}
private class BasePanel extends Node {
}
my problem is:
I have a bunch of different classes all extending a base class (Identifiable).
I need to assign to some of the sub-class a certain value (securityLevel) which should be changeable and assigned to all member of the class (i.e.: it should be static).
I need to access the classes via the common ancestor.
How do I do this?
The first thing which came to mind is to have a dedicated interface (ISecurity) defining either the values or a static method to access them and let the actual classes either not to implements it and, if they do, to override the static field (or method to retrieve it).
However this is not possible for two reasons:
The current Java language does not allow static members in interfaces.
Even if it would allow it it would not be possible to #Override it.
How can I code around the problem?
The only way I found is:
add a non-static member (public Class getValueProvider()) to base class to retrieve the value returning null.
in the interested classes #Override the non-static method returning the value of a private static Class getValueProvider() implementing setters and getters for the wanted value.
use the retrieved class instance to obtain the requested value (or skip everything if the return is null).
This is very ugly and there's no way to enforce the correct implementation in sub-classes.
You could try a service/factory type of implementation. Or have some sort of class object that stores security (SecuritySettings) and send in the current Identifiable object to get security level
public class Identifiable { }
public class SampleUser extends Identifiable { }
public class ExampleUser extends Identifiable { }
public class UserService
{
public int SampleUserSecurity = 0;
//Or an array/dictionary structure
public int GetSecurityLevel(Identifiable user)
{
if(user instanceof SampleUser)
{
return SampleUserSecurity;
}
}
public SampleUser CreateSampleUser()
{
return new SampleUser();
}
public ExampleUser CreateExampleUser()
{
return new ExampleUser();
}
}
You could define Identifiable to be an abstract class. Additionally, you can define another abstract class that extends Identifiable and adheres to your restrictions, ie holds the static variable and whatever methods may be necessary.
I would try to avoid any static members. Static members in java are always clamsy (you cannot override just hide them, etc.)
I'm not sure if I understand your problem corret but I suggest you construct the objects with a context interface or something. The objects then cann access these context interface if they area allowed to return a value or have to return a special value.
The one creating all these objects can pass the same object and so control the behaviour. This object could then be held static (like a singelton)
I'm sorry if this question may be asked all the time, but I searched and couldn't find an sufficient answer.
How to disable inheritance of private members/fields if they are being accessed by a public member/method?
So consider this:
public class A {
private MemberA a = new MemberA();
public void foo(TypeA x) {
a.methodCall(); //access to a
}
}
public class B extends A {
private MemberB b = new MemberB();
public void foo(TypeB x) {
b.methodCall();
}
}
If you hit the debugger you'll see, that B has a field a by type MemberA. That's in compliance with Java rules because if a public member has access to a private member it will be inherited.
But in B "a" is useless and only taking memory - even if you don't instanciate it in the constructor of B, because B calls it's super constructor and it has to be instanciated in A because a has very much use for a.
I need to have same method names for A and B and they have to be public, but since they do fundamentally different things but also share common logic B needs to be inherited from A.
So basically, I need to know how to overload and override a method the same time. Or duplicate code. What to do?
This situation -- where a class has data members that you do not want to inherit -- is called the "Refused Bequest" antipattern, and what it generally means is that your inheritance relationship is wrong. Rather than having B extend A, you need an interface C that both implement independently. If there is significant implementation that you do want to share, then perhaps you could introduce an abstract base class that A and B could share.
Alternatively, it could also be that MemberA and MemberB (not A and B) share the common interface (or abstract class), say "Member", including methodCall(). You could then do
public class A {
protected Member myMember; // sounds like an Austin Powers movie...
// in the constructor
myMember= new A();
}
while, in class B, the constructor does this instead: (or use DI, etc...)
myMember = new B();
and in foo(), which need not be overloaded, you call myMember.methodCall().
Without knowing your problem it's hard to say if this approach or #Ernest's is better. In either case you are looking for common functionality, and it will likely be the same amount of work.