Reflection/List properties: Difference between revisions

From Rosetta Code
Content added Content deleted
(added java)
Line 10: Line 10:


public class ListFields {
public class ListFields {
public int examplePublicField;
public int examplePublicField = 42;
private boolean examplePrivateField;
private boolean examplePrivateField = true;
public static void main(String[] args) {
public static void main(String[] args) throws IllegalAccessException {
Class clazz = ListFields.class;
ListFields obj = new ListFields();
Class clazz = obj.getClass();


System.out.println("All public fields (including inherited):");
System.out.println("All public fields (including inherited):");
for (Field f : clazz.getFields()) {
for (Field f : clazz.getFields()) {
System.out.println(f);
System.out.printf("%s\t%s\n", f, f.get(obj));
}
}
System.out.println();
System.out.println();
System.out.println("All declared fields (excluding inherited):");
System.out.println("All declared fields (excluding inherited):");
for (Field f : clazz.getDeclaredFields()) {
for (Field f : clazz.getDeclaredFields()) {
System.out.println(f);
System.out.printf("%s\t%s\n", f, f.get(obj));
}
}
}
}
Line 30: Line 31:
<pre>
<pre>
All public fields (including inherited):
All public fields (including inherited):
public int ListFields.examplePublicField
public int ListFields.examplePublicField 42


All declared fields (excluding inherited):
All declared fields (excluding inherited):
public int ListFields.examplePublicField
public int ListFields.examplePublicField 42
private boolean ListFields.examplePrivateField
private boolean ListFields.examplePrivateField true
</pre>
</pre>



Revision as of 19:18, 6 August 2016

Task
Reflection/List properties
You are encouraged to solve this task according to the task description, using any language you may know.
Task

The goal is to get the properties of an object, as names, values or both.

Some languages support dynamic properties, which in general can only be inspected if a class' public API includes a way of listing them.

Java

<lang java>import java.lang.reflect.Field;

public class ListFields {

   public int examplePublicField = 42;
   private boolean examplePrivateField = true;
   
   public static void main(String[] args) throws IllegalAccessException {
       ListFields obj = new ListFields();
       Class clazz = obj.getClass();
       System.out.println("All public fields (including inherited):");
       for (Field f : clazz.getFields()) {
           System.out.printf("%s\t%s\n", f, f.get(obj));
       }
       System.out.println();
       System.out.println("All declared fields (excluding inherited):");
       for (Field f : clazz.getDeclaredFields()) {
           System.out.printf("%s\t%s\n", f, f.get(obj));
       }
   }

}</lang>

Output:
All public fields (including inherited):
public int ListFields.examplePublicField	42

All declared fields (excluding inherited):
public int ListFields.examplePublicField	42
private boolean ListFields.examplePrivateField	true

JavaScript

There are multiple ways of getting property names, each of which include different subsets of an object's properties, such as enumerable or inherited properties. Properties in JavaScript can be enumerable or non-enumerable; enumerable properties are accessable when looping over the object with for. Object.getOwnPropertyNames().

<lang javascript>var obj = Object.create({

   name: 'proto',
   proto: true,
   doNothing: function() {}
 }, {
   name: {value: 'obj', writable: true, configurable: true, enumerable: true},
   obj: {value: true, writable: true, configurable: true, enumerable: true},
   'non-enum': {value: 'non-enumerable', writable: true, enumerable: false},
   doStuff: {value: function() {}, enumerable: true}

});

// get enumerable properties on an object and its ancestors function get_property_names(obj) {

   var properties = [];
   for (var p in obj) {
       properties.push(p);
   }
   return properties;

}

get_property_names(obj); //["name", "obj", "doStuff", "proto", "doNothing"]

Object.getOwnPropertyNames(obj); //["name", "obj", "non-enum", "doStuff"]

Object.keys(obj); //["name", "obj", "doStuff"]

Object.entries(obj); //[["name", "obj"], ["obj", true], ["doStuff", function()]] </lang>

Python

The dir() function and Python's inspect module both will list properties.

<lang python>class Parent(object):

   __priv = 'private'
   
   def __init__(self, name):
       self.name = name
   
   def __repr__(self):
       return '%s(%s)' % (type(self).__name__, self.name)
   
   def doNothing(self):
       pass

import re

class Child(Parent):

   # prefix for "private" fields
   __rePrivate = re.compile('^_(Child|Parent)__')
   # used when setting dynamic property values
   __reBleh = re.compile('\Wbleh$')
   @property
   def reBleh(self):
       return self.__reBleh
   
   def __init__(self, name, *args):
       super(Child, self).__init__(name)
       self.args = args
   
   def __dir__(self):
       myDir = filter(
           # filter out private fields
           lambda p: not self.__rePrivate.match(p),
           list(set( \
               sum([dir(base) for base in type(self).__bases__], []) \
               + type(self).__dict__.keys() \
               + self.__dict__.keys() \
           )))
       return myDir + map(
           # dynamic properties
           lambda p: p + '_bleh',
           filter(
               # don't add dynamic properties for methods and other special properties
               lambda p: (p[:2] != '__' or p[-2:] != '__') and not callable(getattr(self, p)),
               myDir))
   
   def __getattr__(self, name):
       if name[-5:] == '_bleh':
           # dynamic '_bleh' properties
           return str(getattr(self, name[:-5])) + ' bleh'
       if hasattr(super(Child, chld), '__getattr__'):
           return super(Child, self).__getattr__(name)
       raise AttributeError("'%s' object has no attribute '%s'" % (type(self).__name__, name))
   
   def __setattr__(self, name, value):
       if name[-5:] == '_bleh':
           # skip backing properties that are methods
           if not (hasattr(self, name[:-5]) and callable(getattr(self, name[:-5]))):
               setattr(self, name[:-5], self.reBleh.sub(, value))
       elif hasattr(super(Child, self), '__setattr__'):
           super(Child, self).__setattr__(name, value)
       elif hasattr(self, '__dict__'):
           self.__dict__[name] = value
   
   def __repr__(self):
       return '%s(%s, %s)' % (type(self).__name__, self.name, str(self.args).strip('[]()'))
   
   def doStuff(self):
       return (1+1.0/1e6) ** 1e6

par = Parent('par') par.parent = True dir(par)

  1. ['_Parent__priv', '__class__', ..., 'doNothing', 'name', 'parent']

inspect.getmembers(par)

  1. [('_Parent__priv', 'private'), ('__class__', <class '__main__.Parent'>), ..., ('doNothing', <bound method Parent.doNothing of <__main__.Parent object at 0x100777650>>), ('name', 'par'), ('parent', True)]

chld = Child('chld', 0, 'I', 'two') chld.own = "chld's own" dir(chld)

  1. ['__class__', ..., 'args', 'args_bleh', 'doNothing', 'doStuff', 'name', 'name_bleh', 'own', 'own_bleh', 'reBleh', 'reBleh_bleh']

inspect.getmembers(chld)

  1. [('__class__', <class '__main__.Child'>), ..., ('args', (0, 'I', 'two')), ('args_bleh', "(0, 'I', 'two') bleh"), ('doNothing', <bound method Child.doNothing of Child(chld, 0, 'I', 'two')>), ('doStuff', <bound method Child.doStuff of Child(chld, 0, 'I', 'two')>), ('name', 'chld'), ('name_bleh', 'chld bleh'), ('own', "chld's own"), ('own_bleh', "chld's own bleh"), ('reBleh', <_sre.SRE_Pattern object at 0x10067bd20>), ('reBleh_bleh', '<_sre.SRE_Pattern object at 0x10067bd20> bleh')]

</lang>