Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I've seen some discussions in StackOverflow about this subject, but I didn't see something that helped me understand the following point:
I'm coming from C++ background and lately I started to learn Java.
In C++ when protected is used only a subclass can access the member (the analog to Field in Java).
In C++ there is also the "friend" classes that can have access to private/protected mambers of the class that giving "friendship".
This is little bit analogous to "package" field modifier in Java (default field modifier), except that in C++ a friendship gives access to all private members, but in Java the access from classes in the same package is specific for a class field.
What I couldn't understand is, assuming that I want to give access only to subclasses, this is something I can do in C++ by declaring the members protected in a class that doesn't "give" friendships.
But in Java, I don't know how can I do it, since by using "protected" field modifier - I also give access to all classes in the package.
The only way that I find to do it is to declare the field protected and have the class isolated in its package.
From here, what I conclude is that the grouping of classes in one package must be done on basis of "friendship" between the classes.
Is this indeed the leading consideration in package grouping?
Another thing I don't understand,
In Java, assuming I have two fields in the class A: b,c.
I want to give B access to b but not to c,
and I want to give C access to c but not to b.
and to the "World" I want b,c to be hiden.
How can it be done?
I guess B,C should be both in the same package as A.
but by declaring b,c with package modifier I let B,C access both to b and c.
Is there a way in Java to do it?
Hope for some explanation of this subject
In C++ when protected is used only a subclass can access the member
(the analog to Field in Java).
Access specifiers are also for member functions / methods, not just member variables / fields.
In C++ there is also the "friend" classes that can have access to
private/protected mambers of the class that giving "friendship". This
is little bit analogous to "package" field modifier in Java (default
field modifier), except that in C++ a friendship gives access to all
private members, but in Java the access from classes in the same
package is specific for a class field.
There are not only friend classes but also functions.
It's true that Java's package-private access is similar, but it's not a complete replacement. A better way to put it would be that those two features have a subset of problems they solve. There are problems that can be solved by friend but not by package-private, and vice versa.
What I couldn't understand is, assuming that I want to give access
only to subclasses, this is something I can do in C++ by declaring the
members protected in a class that doesn't "give" friendships.
But in Java, I don't know how can I do it,
The answer is: You cannot.
since by using "protected" field modifier - I also give access to
all classes in the package.
Exactly.
The only way that I find to do it is to declare the field protected and
have the class isolated in its package.
Technically, yes. But this creates other problems. Your class will no longer be able to access package-private elements of its previous package. Let's say your BaseClass used to be in com.example.one. You move it to com.example.two. Now it will no longer be able to access other package-private classes of com.example.one.
Is this indeed the leading consideration in package grouping?
Yes, Java is designed like this. You can try to fight the language rules, but that's a losing battle in any programming language.
Another thing I don't understand, In Java, assuming I have two fields
in the class A: b,c. I want to give B access to b but not to c, and I
want to give C access to c but not to b. and to the "World" I want b,c
to be hiden. How can it be done?
It cannot be done in a clean way (by clean I mean: without any hacks that would require you to inspect the call stack at runtime and throw exceptions).
If you are concerned about this scenario because you are designing a public API, a low-tech solution which usually works perfectly is to create one or more *.internal packages and clearly document the fact that those are not supposed to be used in client code.
Those are quite a bunch of questions together...
But in Java, I don't know how can I do it, since by using "protected" field modifier - I also give access to all classes in the package.
True, there's no way to give access only to subclasses but not to classes in the same package. It was a design decision taken ages ago...
The only way that I find to do it is to declare the field protected and have the class isolated in its package.
This is technically correct, though it would be of little usage. Packaging of classes is meant to be used for grouping related classes, where 'related' means "classes that fulfil a specific relation", i.e. they belong to the same use case, belong to the same architectural layer, are in charged of the same entity, etc.
From here, what I conclude is that the grouping of classes in one package must be done on basis of "friendship" between the classes. Is this indeed the leading consideration in package grouping?
I believe I have already answered this in the preceding paragraph: packaging is meant to group related classes according to some specific criteria.
For your A, B and C classes example with attributes:
I guess B,C should be both in the same package as A. but by declaring b,c with package modifier I let B,C access both to b and c. Is there a way in Java to do it?
The answer is no, there's no simple, clean way to do it. You could achieve it with some hack or some more advanced techiques, but, again, this was part of the decisions taken by language designers ages ago...
It is implicitly assumed that all classes in a package "know" each other (because they were written by the same person/company/organization). So they either don't access protected fields, or, if they do, they know how to do it properly.
The assumption is that classes in the same package are more related to each other than a parent is to a derived class, because the derived class might virtually be written by anyone else. So they decided private protected is more restricted than protected.
So, I think you should not worry about the way classes in the same package can access each others' fields. In general, I just don't use this feature, except when I write iterators.
If you have two fields, you might make them internal classes, so that they have access to private fields (again, the logic is: if a class is inside another class, it knows about the semantic of that class) and can expose this access to their derived classes via protected methods.
Of course, you can invent some complex token exchange protocol to only make that field accessible to instances of B/C, but it'd be a remarkable overhead, and another object can still use reflection to gain access to all private members, unless you disable it via security policies, which isn't usually the case, but again, security policies are ultimately decided by the owner of the JVM.
So, in the end, the preferred way to do what you say in Java is to either put them in the same package or write B and C as internal classes of A, so that they can directly access private members of A and expose them to their derived classes.
public class A {
public static abstract class B {
protected Whatever getWhatever(A a) { return a.b; }
protected void setWhatever(A a, Whatever value) { a.b = value; }
}
public static abstract class C {
protected Whatever getWhatever(A a) { return a.c; }
protected void setWhatever(A a, Whatever value) { a.c = value; }
}
private Whatever b;
private Whatever c;
}
again, you always assume classes in the same package will never do anything bad.
Short answer: there's no way to do it.
If you're worried about intrusion from clients injecting a class in your package to gain illegal access, you can move the sensitive code in a separate package, and make the package sealed in the jar you deliver it in: http://docs.oracle.com/javase/tutorial/deployment/jar/sealman.html
Related
How to make a member of a class to be accessible only in subclasses in any packages? Protected is not a solution since it will open the member to other non subclasses classes.
Java does not provide absolute encapsulation. Some amount of discipline is required on the part of the programmer - both the original designer and anyone that uses a published API - to abide by some rules that are outside of the language. Regarding member access, you have identified one such case. What you want is not possible in Java.
Just to put this in broader perspective, I'd point out that even private members can be accessed by other classes if a programmer is willing to go far enough to do it. Calls made via JNI do not have to respect any of the access modifiers. See, e.g., Can a native method call a private method?
Other examples of out-of-language norms include the contract for equals/hashCode, which must be met for classes to behave well with respect to collections but is not enforced at the level of the language.
I understand why you want to do this; however, Java simply does not provide that capability.
You could do abstract class with protected member, and implement it in another packages. Consider you created some lib and design extensability for certain things. Later users of your lib will implement realizations of your class and has access to protected member and in same time not able to create implementation classes in your package. In example FilterReader class, it design for extensibility, after you implement it in somewhere in your code outside java.io package that protected fields and methods will be private to other classes in your package.
What you are trying to achieve ist not possible during to acces control:
https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
You may rethink your software design, since yout problem is caused by architecture.
please be more specific in your question for getting further answer.
Solving your problem may cause sideeffects and is not in a OOD manner.
The only way to acces the private member is using an getter method with same visibilty issuses.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
In C# the spec says:
Instance constructors, destructors, and static constructors are not
inherited, but all other members are, regardless of their declared
accessibility (§3.5). However, depending on their declared
accessibility, inherited members might not be accessible in a derived
class.
so private fields are inherited into a derived class but they are not accessible.
However the Java spec says:
Only members of a class that are declared protected or public are
inherited by subclasses declared in a package other than the one in
which the class is declared.
so private fields are not inherited into a derived class.
And what does explain the OOP theory? Is correct C# or Java designers?
A bit confused on this aspect.
P.S.
I haven't C++ experience? What does C++ designers says on this?
Well, the C# version is more-clear because even in Java, private fields will be available as part of the child object but they will no be directly accessible unless you have a public getter in the parent class to get its value.
You can actually use reflection to make private fields (of the parent ) accessible and read their values directly.
Keeping the things simple and clean, taking some part of quote you mentioned for c++
However, depending on their declared accessibility, inherited members might not be accessible in a derived class.
The same thing happens in Java as well. You can't access private fields in Java too.
There are methods around them to access which is another story (encapsulation)
Answering at least the C#/Java-part as I don´t know much on C++.
However, depending on their declared accessibility, inherited members might not be accessible in a derived class.
The C#-spec seems to be a bit more meaningful, although Java handles private mebers the same way. The private members from base-class also exist in Java (however they are not inherited, see are private fields inherited in Java?). As you cannot access them this is not usefull anyway. The internals however are of course initialized by setting the private members also. So instances of your derived class of course have all the private members of the base-class, inheritance however means any kind of polymorphism which implies you might be able to override (assuming your member is not static or final/selead) them which makes no sense at private members.
So coming to the chase there should be no need for accessing the internals at all, neither in C# nor in Java nor anywhere else. Simply assume your derived instances get all the base-members fully-initialized and do your actual work.
Relating to what you call "OOP-theory" I doubt there is a cleaner answer as for this principle (which is implemented in different ways in the mentioned languages)private members have no relevance at all. OOP merely handles the interactions between objects with their surrounding not their actual internals.
I think the confusion is related to a confusing wording. In Java or C# or any other OO language, if you construct a child you have to call the parent constructor, because the parent is part of the child. Very often the call of the parent constructor is done implicitly.
So the private attributes from the parent are always present somewhere within the child object. Then OOP ensures, that you can not access the private attributes within the child. This encapsulation is the important point. And this fact is described by the two references: Either you call it the attributes are not inherited or you say that they are inherited but not visible.
As mentioned above you can (ab)use the reflection library to get around these restriction.
How do I change my mistakenly c#-ish design to work with sensible access protection in java?
Here is my super class
abstract class Parent {
protected parentVariable;
protected parentMethod() {
//These methods and variables contain internal workings of my sub-classes
//to avoid repetition
// I don't want classes elsewhere in the package (that don't inherit from class) to see these.
}
}
I have sub classes that have shared internal working, which I've stuck it in the super class. It's still hidden to the other classes and usable by sub classes. Wait, no: this isn't c#, this is java.
Protected(c#) != Protected(java) ≈≈ Internal(C#).
c# protected = Access is limited to the containing class or types derived from the containing class.
java protected = Access is limited to the current package
Everything in the package can see access these. That's far too permissive for these internal workings.
How do I solve this? Do I have to bring the shared code down to the sub-classes and use "private" at the cost of code repetition? Was my use of parent classes bad design in the first place? Do I have to squirrel these inheritance trees away in new packages?
There is no access modifier that allows visibility to subclasses but not to classes of the same package.
But that's not such a big problem because classes in a given package are supposed to be "friend", cooperate, and be released all at the same time.
Even if they see some fields and methods that they shouldn't use, the other classes of the package are not part of any external API that you have no control on, and the protected methods are not accessible to the external code.
So, just document that these methods and fields shouldn't be used so that you or your coworkers don't mistakenly use them. Or put this class in its own package if you're really concerned about same-package visibility.
I know this applies to many languages, and not just Java, but that is the language I'm most familiar with.
I understand what the modifiers do, and how to use them. I just want to know, why do we need them? Why can't every object be accessible, whether or not it needs to be?
The reason becomes more apparent when you have to maintain a larger project. When a method or variable is public, you have to be careful when you make changes to it, because you never know which parts of the codebase rely on its exact behavior.
But when a variable or method is private, you know that it is not used outside of the class. That means there is a lot less code you have to pay attention to when you make changes.
By making class features private and public, you clearly separate the interface to the outside world from the internals. The less you exposes to the outside world, the more freedom you have with what the internal implementation does.
When you, for example, always make variables private and accessed them through getters and setters, you can later change them from a variable to a computed value, and then even later add caching to the computation for performance reasons. When it would be a public variable, you would have to change code everywhere the variable is used. But when you expose it to the outside world through getters and setters, all other code can keep using the class as if nothing had changed.
Making fields and methods private keeps other classes from improperly depending on the specific details of how a class works. The public interface (and the best case of all, an actual interface) describes how client code should interact with a library based on the semantics of the work being done. The implementer is then free to use whatever appropriate techniques to implement that interface and can make significant behind-the-scenes changes knowing that the client code will keep working.
An everyday example is the Collections group of interfaces. Most of the time, it's not important logically for code to know what particular kind of Set is in use, just that it's a collection that supports certain operations and doesn't have duplicates. This means that a method that accepts a Set<Integer> will work with any Set, including HashSet and ImmutableSet, because the person who wrote the interface wasn't poking around in the implementation's internals.
An example where this breaks down is the unfortunate tendency of some programmers to use packages in the com.sun namespace, especially when using cryptography. Upgrading to a new version of the JRE routinely breaks this code, which would have worked fine if the programmer had used the proper javax.crypto interfaces and factory methods instead of poking around in the JVM internals.
More or less they are used to control who can access your member variables and functions. It's the broader concept of encapsulation at work in Java(http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)).
From the Oracle Docs:
Access level modifiers determine whether other classes can use a
particular field or invoke a particular method. There are two levels
of access control:
At the top level—public, or package-private (no explicit modifier).
At the member level—public, private, protected, or package-private (no
explicit modifier).
http://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
As to why you should do this:
It has to do with intent of use. It would probably be best described as a design choice that helps guide usage through-out the code-base. By marking something private you are telling other developers that this field or method should not be used outside it's current purpose. It really becomes important on large projects that shuffle developers over time. It helps communicate the purpose & intended uses of classes.
To avoid other classes having direct access to internal members of the class.
This is most useful for avoiding that member variables are mutated in an uncontrolled way (e.g. without proper validation, without notifying listeners, ...).
Another reason to avoid this is that the internal implementation may change at any time but you don't want to break code that uses it.
As others have noted, the concept is called Encapsulation.
Access modifiers are there to set access levels for classes, variables, methods and constructors. This provides an individual with the chance of controlling better the privacy of the application. There are 4 access modifiers.
Modifier | Class | Package | Subclass | World
no modifier:--|----yes----|------yes--------|--------no--------|-----no----|
private:-------|----yes----|-------no--------|--------no--------|-----no----|
public:--------|----yes----|------yes--------|-------yes-------|----yes----|
protected:---|----yes----|------yes--------|-------yes-------|-----no-----|
Regarding your question, we do need and use access modifiers because we need to restrict whom can call our program and in what way.
Also, when it comes to variables if you make something public, that means that I have direct access to it. Therefore, I am allowed to do whatever I want without following your guidelines through your methods.
For example:
public int maxUsers;
public void setMaxUsers(int users) throws IllegalArgumentException{
if(users > 0 && users <= 1000){
maxUsers = users;
}else{
throw new IllegalArgumentException("The users can not be less than 0 or greater than 1000")"
}
}
Imagine your whole program being based on its maxUsers. Since, you give me the right to access that variable directly, I could do this: maxUsers = -15; and not use the setMaxUsers method, which will simply make your program behave in an abnormal way (in the best case).
Explanations
A private member is only accessible within the same class as it is declared.
A member with no access modifier is only accessible within classes in the same package.
or
If a variable is set to protected inside a Class, it will be accessible from its sub classes defined in the same classes or different package only via Inheritance.
A protected member is accessible within all classes in the same package and within subclasses in other packages.
A public member is accessible to all classes (unless it resides in a module that does not export the package it is declared in
Here's a better version of the table. (Future proof with a column for modules.)
I realise that this is a very basic question, but it is one which has always bothered me. As I understand things, if you declare a field private in Java then it is not visible outside of that class. If it is protected then it is available to inherited classes and anything in the same package (correct me if either of those definitions is incorrect).
Does this mean it is not possible to declare a field that is accessible to only inherited classes and not other non-inherited classes in the same package?
I appreciate that there are ways around this, but are there instances when you would want to have this sort of behaviour?
Obviously the above question applies to methods as well as fields.
Many thanks.
See: http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html
Package > Subclasses, you can never have a field only visible by subclasses but not by classes from the same package.
Basically:
private: Accessible only by the class.
public: Accessible by any class.
protected: Accessible by the class, all inherited classes and the classes of the current package (edited).
no scope defined: Accessible by all classes of the current package.
more information here.
Yes, Java's protected access is a little bit odd in that way. I can't immediately see why it's desirable at all. Personally it doesn't bother me for fields as I don't like non-private fields anyway (other than constants) but the same is true for other members.
.NET doesn't have the concept of package/namespace access visibility at all, but it has an alternative which is assembly (think "jar file" - not exactly the same, but close). Frankly I'd like to have namespace and deployment-unit visibility options, but it seems I'm doomed to disappointment...