How do I control visibility to field in my Java classes? - java

How can I differentially control access to members of any class? Let's say I have three classes:-
Class A
{
int a;
int b;
}
Class B
{
Access to only 'a' and not 'b'
}
Class C
{
Access to only 'b' and not 'a'
}

One way would be to use aspect-oriented programming. You can check to see the accessing package or class and prohibit access.
AspectJ can be used to enforce that classes in the persistence tier are not accessed in the web tier, only from the service tier. Here's an example:
http://blog.jayway.com/2010/03/28/architectural-enforcement-with-aid-of-aspectj/

Interface time:
interface IHaveA { int a {get;set;} }
interface IHaveB { int b {get;set;} }
Class A : IHaveA, IHaveB
{
public int a {get;set;}
public int b {get; set;}
}
Class B
{
IHaveA _iHaveA;
C(IHaveA iHaveA)
{
_iHaveA = iHaveA;
}
}
Class C
{
IHaveB _iHaveB;
C(IHaveB iHaveB)
{
_iHaveB = iHaveB;
}
}
Then new up B and C like this:
static Main()
{
A a = new A();
B b = new B(a);
C c = new C(a);
}

Here is a really crude idea.
Have A have a function to take an observer derived from B, and another function to take an observer derived from A.
class A
{
int a;
int b;
void getAObserver(B bInstance);
void getBObserver(C cInstance);
}
Then have A can call functions such as aWasUpdated or bWasUpdated on the instances make the member a and b sort of psuedo public to the specific classes.

A really crude way of implementing this would be
Class A {
private int a ;
private int b ;
public int getA( Object obj) throws userDefinedIllegalAccessException {
//check if obj isInstance of B
// If yes return a
// else throw userDefinedIllegalAccessException
}
public int getB( Object obj) throws userDefinedIllegalAccessException {
//check if obj isInstance of c
// If yes return b
// else throw userDefinedIllegalAccessException
}
}
class B {
public void checkAccessValue() {
try{
A objA = new A() ;
System.out.println(objA.getA(this) ;
System.out.println(objA.getB(this) ;
}
catch(userDefinedIllegalAccessException udException){
}
}
}
class C {
public void checkAccessValue() {
try{
A objA = new A() ;
System.out.println(objA.getA(this) ;
System.out.println(objA.getB(this) ;
}
catch(userDefinedIllegalAccessException udException){
}
}
}

Related

In Java, is there a way to get access to an object from inside an object created/used by that class?

Let's say I have a class that instantiates and uses another class. From the second class, is it possible to gain access to the first one?
For example:
public class A {
public B obj = new B();
public void something() {
b.somethingElse();
}
}
public class B {
public void somethingElse() {
A owner = getCallingObject();
//the object of class A that called b.somethingElse() is now stored in owner
}
public Object getCallingObject() {
// ?????
// returns the A that instantiated/owns this B
}
}
I know how to get the Class of that object using something like this:
private String getCallerClassName() {
StackTraceElement[] stElements = Thread.currentThread().getStackTrace();
for (int i = 1; i < stElements.length; i++) {
StackTraceElement ste = stElements[i];
if (!ste.getClassName().equals(B.class.getName()) && ste.getClassName().indexOf("java.lang.Thread") != 0)
return ste.getClassName();
}
return null;
}
which I got from a different question: How to get the caller class in Java.
Is there a way to get a pointer to the caller object?
If you control the source code, and if B can only be created by an A object, you could make B a non-static inner class, and then you would automatically get a reference back to the creator of the class, through the A.this pointer. Note this isn't the caller of B::somethingElse(), but the creator of B, which may or may not be the same thing, depending on your use case.
public class A {
public B obj = new B();
public void something() {
obj.somethingElse();
}
void thereAndBackAgain() {
}
public class B {
public void somethingElse() {
A owner = A.this;
owner.thereAndBackAgain();
}
}
}

Function the uses an object relying in two different packages

I have the sama java object TestData in to packages (A & B). I have made a function that processes the object for a standard business functionality.
CommonFunc.java:
import A.TestData ;
class CommonFunc
{
/// .....
public static TestData processTestData(Date d1, String s1){
TestData testData = new TestData ();
/// set some testData porperties based on d1 and s1
/// e.g : testData.setInitialDate(d1);
return testData ;
}
}
The problem here is that the compiler has to load the object from one of the packages lets say package (A), so when I expect the data to be returned to a local variable from package (B) I get incompatible type error :
File using B TestData and needs to call the function processTestData:
import B.TestData;
// ...
TestData obj = CommonFunc.processTestData(new Date(), "test");
// ...
Is there a way to overcome this problem keeping a common function for both?
Is there a way to overcome this problem keeping a common function for both?
No and yes. On the general case, you cannot.
But you can, IFF you can make the two classes adopt the same interface, with the common methods declared in the same interface. See below, with apologies for the change in the class names:
interface C {
public Date getA();
public void setA(Date a);
}
interface C_Factory <X extends C> {
X createInstance();
}
class C1 implements C {
Date a;
int b;
public C1() {
super();
}
public Date getA() { return a; }
public void setA(Date a) { this.a = a; }
public int getB() { return b; }
public void setB(int b) { this.b = b; }
}
class C2 implements C {
Date a;
float b;
public C2() {
super();
}
public Date getA() { return a; }
public void setA(Date a) { this.a = a; }
public float getB() { return b; }
public void setB(float b) { this.b = b; }
}
public class CommonFunc {
// You need this extra param to create instances----
// V
static <X extends C> X doSomething(Date d, Class<X> clazz)
throws InstantiationException, IllegalAccessException
// You'll have to accept those exceptions as well
{
// the next statement uses clazz as a factory for new X instances
// As such, you can abstract the method further and use
// a custom Factory class instead.
X toret=clazz.newInstance();
toret.setA(d);
// something else
return toret;
}
// A custom factory variant of the above
static <X extends C> X doSomething(Date d, C_Factory<X> factory)
{
X toret=factory.createInstance();
toret.setA(d);
// something else
return toret;
}
static public void main(String[] args) {
try {
C1 c1=doSomething(new Date(), C1.class);
C2 c2=doSomething(new Date(), C2.class);
} catch (InstantiationException | IllegalAccessException e) {
// Should not happen
e.printStackTrace();
}
}
}
I do not see how it is possible in the above example you have posted, The best way out is to make the TestData an interface and have implementations in 2 packages. Then, to decide whether to return A TestDataImpl or B TestDataImpl, take another parameter in the processData, for simplicity, let us say a boolean. Based on true or false instantiate A TestDataImpl or B TestDataImpl and return the same. Where the return type of processData is the interface type
This is probably would be the most straightforward way of reusing the processData method.

How to make class that can only be accessed through interface?

In C# or Java, how can I make a class that can only be instantiate with the Interfaces it implemented on?
Sorry if this question is asked before.
Edit: Sorry for confusing you, and this question is just asked out of curious:
For example I have:
interface iA
{
int addNum();
}
interface iB
{
int minusNum();
}
class A implements iA, iB
{
private int A;
public int addNum()
{
A += 10;
return A;
}
public int minusNum()
{
A -= 10;
return A;
}
}
class TestIface
{
public static void main(String args[]) {
A testA = new A();
iA testiA = new A();
iB testiB = new A();
testA.minusNum(); // No error, it has access to both methods
testA.addNum();
testiA.minusNum();//ERROR
testiA.addNum();
testiB.minusNum();
testiB.addNum();//ERROR
}
}
I wonder if there is a way to prevent dev from just make testA and access both methods.
How about making the constructor private?
class A implements iA
{
public int returnNum()
{
return 10;
}
private A(){}
public static iA getInstance(){
return new A();
}
}
You can make the constructor private and define a static Create method that creates new instances.
public interface ITest
{
}
public class A : ITest
{
private A()
{
}
public static ITest Create()
{
return new A();
}
}
Then the only way to create an instance of your class (besides reflection, but that's another story!) is to call the Create method like this:
ITest test = A.Create();
You cannot instantiate something via an interface. You can only declare it as an interface. If your goal is to make addNum only accessible via iA and minusNum only accessible via iB, you can try explicit interface implementation (although it has its own drawbacks):
class A : iA, iB
{
private int A;
int iA.addNum()
{
A += 10;
return A;
}
int iB.minusNum()
{
A -= 10;
return A;
}
}
This will at least give you the compile time effect you are looking for:
class TestIface
{
public static void main(String args[]) {
A testA = new A();
testA.minusNum(); // does not compile
testA.addNum(); // does not compile
iA testiA = new A ();
testiA.minusNum();//does not compile
testiA.addNum();
iB testiB = new A ();
testiB.minusNum();
testiB.addNum();//does not compile
}
}
However, this does not mean addNum is only accessible via a variable which is declared as iA. To illustrate, you can do:
A testObj = new A ();
(testObj as iA).addNum (); // this will compile
You can even do:
iB testObj = new A ();
(testObj as iA).addNum (); // this will also compile, and execute fine
If you want to further prevent the explicit casting from and to the concrete class, you need have to take the advice others have offered: make your concrete class a nested private class and introduce a factory to produce the instance:
class Factory
{
private class A : iA, iB
{
int iA.addNum () {...}
int iB.minusNum () {...}
}
public iA GetInstanceOfiA ()
{
return new A ();
}
public iB GetInstanceOfiB ()
{
return new A ();
}
}
This still does not prevent the casting from iA to iB, which I guess you have to create two separate concrete classes to cater.

Java Pattern to build object where any one field must be set?

I need to build objects of a class which has 3 fields: A, B and C. A valid object has at least one of A, B or C set by the user. I looked into the Builder Pattern, which is close to what I want, but only 1 field is made mandatory. I want that 1 field which must be set to be any one of the 3 that I have. Any suggestions?
My alternative is to use 7 constructors (for {A}, {B}, {C}, {A,B}, {B,C}, {A,C}, {A,B,C})
You can use a builder for that. Short example with only two fields instead of three:
public final class MyBuilder
{
private X a, b;
public MyBuilder withA(X a)
{
b = null;
this.a = a;
return this;
}
public MyBuilder withB(X b)
{
a = null;
this.b = b;
return this;
}
public MyClass build()
{
if (a == null && b == null)
barf(); // <-- throw exception here
// A and B inherit MyClass
return a != null ? new A(a) : new B(b);
}
}
You can force A, B, or C to be passed in the build() method:
class ValidBuilder {
public ValidBuilder withA(Object a) {}
public ValidBuilder withB(Object b) {}
public ValidBuilder withC(Object c) {}
public ValidObject buildA(Object a) { }
public ValidObject buildB(Object b) { }
public ValidObject buildC(Object c) { }
}

Two questions on inner classes in Java (class A { class B { } })

Sorry for the bad title, but I couldn't think of a better one.
I'm having a class A and a class B which is kind of a sub class of A, like so:
(Is there actually a correct name for it? Isn't "sub class" reserved for inheritance?)
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
B b = a.new B();
A c = ??? b ??? // get "a" back
}
}
From B every property of A can be accessed, therefore both, a.i and b.i, return 0. Now, I'm wondering whether it's somehow possible to retrieve the original object of type A out of b, as b contains everything that a contains? Simple casting apparently doesn't do the trick.
Second one:
class A {
void print() {
System.out.println("This is class A.");
}
class B {
void print() {
// <--- How to access print() of class A (like this.A.print() or smth)?
System.out.println("This is class B.");
}
}
}
You could alternatively also provide me with some good resources on this topic, as I've been too stupid to find a good one so far.
Thanks in advance. :)
There doesn't seem to be a way to access the outer class from outside. But you can do it like this:
class A {
int i = 0;
class B {
final A outer = A.this;
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = b.outer // get "a" back
}
}
ClassName.this will be the instance of the outerclass associated with the instance of an inner class.
You can access it with the ParentClass.this syntax from within the inner class.
e.g.
public class Outter
{
class Inner {
public Outter getOutter()
{
return Outter.this;
}
}
public Inner getInner(){
return new Inner();
}
}
class Runner{
public static void main(String[] args){
Outter out = new Outter();
Outter.Inner inner = out.getInner();
System.out.println(inner.getOutter().toString());
}
}
[Edit: My answer is appropriate for C# programmers, but I can't guarantee that its applicable to Java.]
B is an inner class, not a subclass of A. Additionally, B does not hold an instance of A, so your code as is cannot return any instance of A.
You need to restructure your classes as follows:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
}
Now your B class has a field 'Parent' which returns its parent. You can use these classes as follows (this is C# syntax, because I don't know if Java has a different syntax for instantiating inner classes):
public static void Main(String[] args)
{
A parent = new A();
A.B child = new A.B(child);
A backToParent = child.Parent;
}
Of course, creating your B class in this way seems little funny: technically, you can pass in any parent. It would probably be better to rewrite your A class with a method which returns a B:
class A
{
public class B
{
public A Parent;
public B(A parent)
{
this.Parent = parent;
}
}
public B getChild()
{
return new B(this);
}
}
public static void Main(String[] args)
{
A parent = new A();
A.B child = A.getChild();
A backToParent = child.Parent;
}
this seemed to work for me
class A {
int i = 0;
class B {
int j = 1;
}
}
class Test {
public static void main() {
A a = new A();
A.B b = a.new B();
A c = (A)b.getClass().getDeclaredField("this$0").get(b);
}
}

Categories

Resources