views:

384

answers:

10

This is a question I was asked in an interview: I have class A with private members and Class B extends A. I know private members of a class cannot be accessed, but the question is: I need to access private members of class A from class B, rather than create variables with the same value in class B.

I hope I am clear with this question. Thanks.

A: 

You can use the setters and getters of class A. Which gives same feeling as if You are using a class A's object.

GK
+3  A: 

The architecture is broken. Private members are private because you do not want them accessed outside the class and friends.

You can use friend hacks, accessors, promote the member, or #define private public (heh). But these are all short term solutions - you will probably have to revisit the broken architecture at some stage.

Matt Curtis
What do you mean, "the architecture is broken". He's asking about an interview question that will test his Java knowledge, not about designing a real system.
Robert Petermeier
By the way if you tell them their code is broken in the interview, it could either help or hinder your chances of getting the job. If it helps, it might be a job you will enjoy. Otherwise, you should keep your CV up-to-date.
Matt Curtis
@Robert The architecture is broken because you use private because it's the right thing to do. If that changes, it is a symptom that your design needs changing."Fixing" it by promoting private to protected is like just telling a just few people your ATM PIN - it will probably be OK in the very short term, but you should change it, or get a joint account or something.
Matt Curtis
+1 for #define private public in interview question
Eric
Thanks Eric. I'd strongly suggest winking when you say it :-)
Matt Curtis
preprocessor directives in java LOL!
questzen
Not necessarily. Things like Hibernate and Spring sometimes need to access private fields. You don't want to make those fields public. This is a valid interview question, and one that I'll ask anybody who walks in claiming to know everything.
Milan Ramaiya
+1 because my first thought was "check that your class hierarchy is necessary and not broken" because this type of requirement raises a red flag to me.
Greg Beech
@Reverend If you sometimes need to access private fields, why are they private? (Genuine question, I am not familiar with Hibernate or Spring).
Matt Curtis
By the way I upvoted @Lachlan's answer because, for newbies, it's the safest answer for an interview. However I would also point out that it is a fairly serious design smell and not one you'd want to just patch over beyond the short term.
Matt Curtis
@Matt. One example: Hibernate is an ORM (Object relational mapping). What it does is loads your object from some data source (ie: a database) where you define the mapping from fields to columns. This saves you the trouble of having to write SQL yourself. In some cases you can use JavaBean getters/setters but you may not want to expose that information. Specifically, your architecture may not need access to those inner variables, but if you need to serialize that object to data in a way that can be reloaded (and does not use Java Serialization), it may be necessary to access those values.
Milan Ramaiya
@Matt: On the same note, I will agree that people in general shouldn't be using reflection. There are definite reasons where it should be used and there is no other real option, but this should be left to people who know what they're doing. On the same note, the only time, I've asked that in an interview was when some guy walked in acting like he knew everything under the sun and he had no idea what he was talking about in general.
Milan Ramaiya
@Reverend Thanks for that example, it's a good one. In cases like this I do concede that it's appropriate to access private members. I agree entirely with your sentiments in your follow-up comment though; there are a lot of devs who don't think through what they're doing and end up with the data flow equivalent of spaghetti code :-)
Matt Curtis
+4  A: 

You cannot access private members from the parent class. You have make it protected or have protected/public method that has access to them.

EDIT : It is true you can use reflection. But that is not usual and not good idea to break encapsulation.

fastcodejava
Not true, you cn use reflection.
Milan Ramaiya
+1  A: 

Have you thought about making them protected ? Just to be sure you are aware of this option, if you are then pardon me for bringing up this trivia ;)

Thomas Wanner
+1  A: 

If I'm understanding the question correctly, you could change private to protected. Protected variables are accessible to subclasses but behave like private variables otherwise.

oltman
+13  A: 

The interviewer was either testing your knowledge of access modifiers, or your approach to changing existing classes, or both.

I would have listed them (public, private, protected, package private) with an explanation of each. Then gone on to say that class A would need to be modified to allow access to those members from class B, either by adding setters and getters, or by changing the access modifiers of the members. Or class B could use reflection. Finally, talk about the pros and cons of each approach.

Lachlan Roche
Great job addressing how to deal with question in an interview situation.
Bee
+1. I would definitely have answered it that way.
BalusC
+5  A: 

Reflection? Omitting imports, this should work:

public class A {

    private int ii = 23;

}

public class B extends A {

    private void readPrivateSuperClassField() throws Exception {
        Class<?> clazz = getClass().getSuperclass();
        Field field = clazz.getDeclaredField("ii");
        field.setAccessible(true);
        System.out.println(field.getInt(this));
    }

    public static void main(String[] args) throws Exception {
        new B().readPrivateSuperClassField();
    }

}

It'll not work if you do something like that before the of invocation readPrivateSuperClassField();:

System.setSecurityManager(new SecurityManager() {
        @Override
        public void checkMemberAccess(Class<?> clazz, int which) {
            if (clazz.equals(A.class)) {
                throw new SecurityException();
            } else {
                super.checkMemberAccess(clazz, which);    
            }
        }
    });

And there are other conditions under which the Reflection approach won't work. See the API docs for SecurityManager and AccessibleObject for more info. Thanks to CPerkins for pointing that out.

I hope they were just testing your knowledge, not looking for a real application of this stuff ;-) Although I think an ugly hack like this above can be legit in certain edge cases.

Robert Petermeier
Robert, that only works if your process has privilege to do so.
CPerkins
+2  A: 

By using public accessors (getters & setters) of A's privates members ...

wj
A: 

Private will be hidden until you have been given the right access to it. For instance Getters or setters by the programmer who wrote the Parent. If they are not visible by that either then accept the fact that they are just private and not accessible to you. Why exactly you want to do that??

Shaaf
A: 

I don't know about Java, but in some languages nested types can do this:

    class A {
        private string someField;
        class B : A {
            void Foo() {
                someField = "abc";
            }
        }
    }

Otherwise, use an accessor method or a protected field (although they are often abused).

Marc Gravell