Accessing Parent's Protected Variables

Accessing parent's protected variables

Member functions of a particular class only have access to protected members of base classes that actually are base class subobjects of objects of their own class type (or more derived types).

Members of one class do not have access to protected members of other instances of that base class and so are also forbidden from accessing protected members through a reference or pointer to the base class type even if at runtime that pointer or reference might be to an object that is of the type of the class whose member function is attempting the access. Access control is enforced at compile time.

E.g.

class X
{
protected:
int z;
};

class Y : X
{
public:
int f( const Y& y )
{
return y.z; // OK
}

int g( const X& x )
{
return x.z; // Error, Y::g has no access to X::z
}
};

In your example, in the expression target->hp, the access to target is legal because you are accessing a member of the current object (which has the type of the class of which the function is a member, Child), but the access to the member hp is not legal because the type of target is not a pointer to Child, but a pointer to Parent.

Protected variables can be accessed within Child Class or Child Object

Disclaimer: the answer is copied from my answer of another question. However no answer from that question is accepted. I believe it also suit this question therefore I am copying the content with some minor editing to here.

protected is a bit interesting in Java. Although we always says "protected" give access to subclass of different package, it is not the whole picture.

For example, if you have Child extending Parent, and there is a protected member in Parent. What you can do in Child is to access that protected member of Child, but not even that protected member of Parent. Sounds a bit strange right although they sounds the same thing?

Quoted from Core Java 9th Edition:

However, the Manager class methods can peek inside the hireDay field
of Manager objects only, not of other Employee objects. This
restriction is made so that you can’t abuse the protected mechanism by
forming subclasses just to gain access to the protected fields

(class Manager extends Employee, and there is a hireDay protected member in Employee, and Manager and Employee are located in DIFFERENT package)

For example,

public class Manager extends Employee {
// accessing protected member of itself
public void foo1() {
System.out.println("" + this.hireDay); // OK
}

// access protected member of instance of same type
public void foo2(Manager manager) {
System.out.println("" + manager.hireDay); // OK
}

// access protected member of instance of super-class
public void foo3(Employee employee) {
System.out.println("" + employee.hireDay); // NOT ALLOWED!
}
}

Which means, protected member allow child class from another package to access through reference of that child class (either this, or another reference that is-a child class)

And, be specific to OP's answer: if callMethod is declared in ChildClass, then NO, you cannot do it and it will not even compile. However if callMethod is declared in ParentClass then everything is fine, because it is simply ParentClass accessing protected member of a ParentClass instance.


Update:

Given criticisms in comment, I think it worth to go to JLS to see what it say:

(Quoted from http://docs.oracle.com/javase/specs/jls/se8/html/jls-6.html#jls-6.6.2.1 about Access to a protected Member, second bullet)

If the access is by a field access expression E.Id, or a method
invocation expression E.Id(...), or a method reference expression E ::
Id, where E is a Primary expression (§15.8), then the access is
permitted if and only if the type of E is S or a subclass of S

This is essentially what I was trying to deliver in the answer:

Within Manager class, manager.hireDay works because manager is a primary expression, and the access is permitted because type of manager is Manager or subclass of Manager.

So, based on JLS, why manager.hireDay works DOES have relationship with type of manager (being the same type).

Accessing protected members in a derived class

A class can only access protected members of instances of this class or a derived class. It cannot access protected members of instances of a parent class or cousin class.

In your case, the Derived class can only access the b protected member of Derived instances, not that of Base instances.

Changing the constructor to take a Derived instance will solve the problem.

Accessing protected variables from parent class in JRuby

Since this fix, package access, private and protected can be exposed by using field_accessor or field_reader:

require 'java'
java_import 'Something'

class Something
field_accessor :somethingelse
end

class Stuff < Something
def anotherstuff
puts self.somethingelse
end
end

Stuff.new.anotherstuff

Prevent Child class from accessing protected member variable of Grandparent class

MatG's comment about searching "c++ inheritance change member access specifier" answered by question. I didn't realize you could change the access modifier of a parent class member in a derived class.

class Parent : Grandparent
{
protected:
void setObj(val) { m_obj = val; }
MyClass getObj { return val; }
private:
using Grandparent::m_obj;
}

Access protected members of base class in grandchild class

Your problem is that you're inheriting from you base classes privately, so public and protected members of the base class get the same access control as private members of the derived class. While possible, private inheritance is a very specific tool and used rarely. In the vast majority of cases, you want public inheritance:

class SmallBox: public Box {
protected:
double height;
};

class TooSmall: public SmallBox {
public:
void setSmallWidth( double wid );
void setHeight(double hei);
double getSmallWidth( void );
double getHeight(void);
};

Done this way, protected members will be visible to all descendants (not just direct children) normally.


If, for some reason, you want to stick with private inheritance, you will have to "promote" the privately-inherited protected members back to protected:

class SmallBox:Box {
protected:
double height;
using Box::width; // make it protected again
};

class TooSmall:SmallBox {
public:
void setSmallWidth( double wid );
void setHeight(double hei);
double getSmallWidth( void );
double getHeight(void);
};


Related Topics



Leave a reply



Submit