Hiding Instance Variables of a Class

Hiding instance variables of a class

In Java, data members are not polymorphic. This means that Parent.var and Child.var are two distinct variables that happen to have the same name. You're not in any sense "overriding" var in the derived class; as you have discovered yourself, both variables can be accessed independently of one another.

The best way forward really depends on what you're trying to achieve:

  1. If Parent.var should not be visible to Child, make it private.
  2. If Parent.var and Child.var are two logically distinct variables, give them different names to avoid confusion.
  3. If Parent.var and Child.var are logically the same variable, then use one data member for them.

How to access hidden superclass instance variables from a subclass body?

AFAIK, instance variables can be only accessed once an object is
created for them.

show() is an instance method. So, it is already operates on an instance.

Besides, as a constructor is invoked, its parent constructor is invoked.

So the constructors of all the hierarchy classes of E that declare their own a variable were invoked.

To refer the a declared in the D parent class, you can do super.a.

Now for the remaining, it is a little tricky but you could cast this to each parent class to be able to refer their a variable :

public void show() {
int a = 0;
int parentD = super.a;
int parentC = ((C)this).a;
int parentB = ((B)this).a;
int parentA = ((A)this).a;
}

Note that you can do that because the a variable declared in the parent classes uses an access modifier that allows D instances to access to.

For example, it would not be possible if you used a private modifier.

Instance variable hiding with inheritance

In the code below, why does println(z.x) display the value of zero?

Because it's referring to the x field declared in A... that's the only one that z.x can refer to, because the compile-time type of z is A.

The instance of B you've created has two fields: the one declared in A (which has the value 0) and the one declared in B (which has the value 2). The instance of A you created is entirely irrelevant; it's a completely independent object.

This is good reason to:

  • Make all of your fields private, drastically reducing the possibility of hiding one field with another
  • Avoid hiding even where it's possible, as it causes confusion

Explain how variable hiding is working in this Java code

Yes, the B class inherits the foo method. But the variable x in B hides the x in A; it doesn't replace it.

This is an issue of scope. The foo method in A sees only the variables that are in scope. The only variable in scope is the instance variable x in A.

The foo method is inherited, but not overridden, in B. If you were to explicitly override foo with the same exact code:

class B extends A
{
int x = 6;

@Override
void foo()
{
System.out.println(this.x);
}
}

Then the variable that would be in scope when referred to by this.x would be B's x, and 6 would be printed. While the text of the method is the same, the reference is different because of scope.

Incidentally, if you really wanted to refer to A's x in the B class, you can use super.x.

Overriding member variables in Java ( Variable Hiding)

When you make a variable of the same name in a subclass, that's called hiding. The resulting subclass will now have both properties. You can access the one from the superclass with super.var or ((SuperClass)this).var. The variables don't even have to be of the same type; they are just two variables sharing a name, much like two overloaded methods.

Hiding instance variables in the EyeInspector or EyeExplorer

I just tried and came up with this:

Imagine this is your class:

Object subclass: #MyClass
instanceVariableNames: 'firstVariable secondVariable thirdVariable'
classVariableNames: ''
category: 'MyCategory'

Then make the following inspector class:

EyeInspector subclass: #MyClassInspector
instanceVariableNames: ''
classVariableNames: ''
category: 'MyCategory'

Add the following class method to MyClass:

inspectorClass
^ MyClassInspector

And overwrite #addInstanceVariable: in MyClassInspector:

addInstancesVariable: elements
elements add: (InstanceVariableEyeElement host: self object instVarName: #firstVariable).
elements add: (InstanceVariableEyeElement host: self object instVarName: #secondVariable)

Inspect an instance of MyClass and it shows only firstVariable and secondVariable but not thirdVariable:

MyClassInspector

Very nice question!

Update: If you want an inspector that shows generally only instance variables specified in the class of an inspected object and not in superclasses of an inspected object you can use this #addInstanceVariable: in your inspector class:

addInstancesVariable: elements
self object class instVarNames do: [:name |
elements add: (InstanceVariableEyeElement host: self object instVarName: name) ]

What does it mean to say Instance variables are not over-rided in java?

It means if you call a method in a superclass it will resolve to the overriden version in a subclass (if your instance is a subclass). However a reference to a member variable will be bound to the declaration of that variable in the class from which the call is made.

Dart: should the instance variables be private or public in a private class?

Making the class private doesn't make its members private and it doesn't make instances of that class inaccessible.

Assume

lib/private_class.dart

class Foo {
final _PrivateClass privateClass = _PrivateClass();
}

class _PrivateClass {
String publicFoo = 'foo';
String _privateBar = 'bar';
}

bin/main.dart

import 'package:so_53495089_private_field_in_private_class/private_class.dart';

main(List<String> arguments) {
final foo = Foo();
print(foo.privateClass.publicFoo);
// print(foo.privateClass._privateBar); // invalid because of ._privateBar
}

You can't declare variables or parameters of the type of a private class or extend or implement the class in another library or create an instance of that class,
but otherwise there is not much difference.

So if the field is supposed to be hidden (internal state) to users of the API, then make the field private.

How do I hide instance variables from the Ruby layer in my C-extension?

The C functions you are looking for are rb_ivar_set and rb_ivar_get.

rb_ivar_set takes three arguments:

  1. the VALUE-type Ruby receiver object
  2. the ID-type ivar name to assign
  3. the VALUE-type Ruby right-hand-side object.

rb_ivar_get takes two arguments:

  1. the VALUE-type Ruby receiver object
  2. the ID-type ivar name to retrieve

Ruby can store instance variables internally with many kinds of ID-type name. The only variable names made visible from the Ruby layer, though, are the ones that begin with @, e.g. rb_intern("@foo"). Leaving out the @ makes the instance variable inaccessible from the Ruby layer, but allows you to store and access it from the C layer.


Here is your code sample with this technique implemented.

#include "ruby.h"

static ID id_push;

static VALUE t_init(VALUE self) {
VALUE arr;
arr = rb_ary_new();
rb_ivar_set(self, rb_intern("arr"), arr); /* <-- */
return self;
}

static VALUE t_add(VALUE self, VALUE obj) {
VALUE arr;
arr = rb_ivar_get(self, rb_intern("arr")); /* <-- */
rb_funcall(arr, id_push, 1, obj);
return arr;
}

VALUE cTest;

void Init_my_test() {
cTest = rb_define_class("MyTest", rb_cObject);
rb_define_method(cTest, "initialize", t_init, 0);
rb_define_method(cTest, "add", t_add, 1); id_push = rb_intern("push");
}

Test it out! It should run like this (I didn't compile the above, there may be typos):

require 'my_test'

class MyTest
def check
return @arr
end
end

t = MyTest.new
t.add(1) #=> [1]
t.check #=> nil

The #check method goes looking for the @arr instance variable and comes up empty-handed. Your instance variables are safe and sound, locked up in the C layer!



Related Topics



Leave a reply



Submit