CS 330 Lecture 39 – Metaprogramming
Agenda
- what ?s
- JSON to Object
- memoize
- @Override
- writing a test runner
Intentions
- I am familiar with the practice of metaprogramming, in which a program can inspect and act on itself—i.e., the program becomes another piece of data than can be inspected and manipulated.
- I am aware of several possible benefits of metaprogramming, including dynamic generation of new program features and objects and tools that automatically profile, test, or transform a program to provide services beyond the traditional compiler.
Code
autobject.rb
#!/usr/bin/env ruby
require 'json'
require 'open-uri'
class JObject
def initialize data
@data = data
end
def self.load io
self.new(JSON.load(io))
end
def method_missing name
name = name.to_s
if @data.has_key? name
value = @data[name]
if value.is_a? Hash
JObject.new(@data[name])
else
value
end
else
super
end
end
end
jo = JObject.load(open 'http://api.openweathermap.org/data/2.5/weather?q=Eau%20Claire,WI')
puts Time.at(jo.sys.sunset)
Superclass.java
package reflecting;
public class Superclass {
public int get() {
return 5;
}
}
Subclass.java
package reflecting;
public class Subclass extends Superclass {
@Usurps
public int getX() {
return 6;
}
public int getZ() {
return 0;
}
}
Usurps.java
package reflecting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Usurps {
}
TestUsurps.java
package reflecting;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class TestUsurps {
public static void main(String[] args) {
test(Subclass.class);
}
public static void test(Class<?> clazz) {
for (Method m : clazz.getDeclaredMethods()) {
Annotation usurps = m.getAnnotation(Usurps.class);
if (usurps != null) {
Class<?> superclazz = clazz.getSuperclass();
try {
superclazz.getMethod(m.getName(), m.getParameterTypes());
} catch (NoSuchMethodException e) {
System.err.println(m.getName() + " usurps nothing in " + superclazz.getName());
}
}
}
}
}
Vector2D.java
package reflecting;
public class Vector2D {
private double x;
private double y;
public Vector2D() {
}
public Vector2D(double x,
double y) {
this.x = x;
this.y = y;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public double getLength() {
return x * x + y * y;
}
public void normalize() {
x /= getLength();
y /= getLength();
}
}
TestTest.java
package reflecting;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface TestTest {
}
TestVector2D.java
package reflecting;
public class TestVector2D {
private static final double EPSILON = 1.0e-3;
@TestTest
public static void testDefaultCtor() {
Vector2D v = new Vector2D();
Assert.assertAlmostEquals("Default ctor zeroes x", 0, v.getX(), EPSILON);
Assert.assertAlmostEquals("Default ctor zeroes y", 0, v.getY(), EPSILON);
}
@TestTest
public static void testOtherCtor() {
Vector2D v = new Vector2D(6, 7);
Assert.assertAlmostEquals("Default ctor sets x", 6, v.getX(), EPSILON);
Assert.assertAlmostEquals("Default ctor sets y", 7, v.getY(), EPSILON);
}
}
TestRunner.java
package reflecting;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class TestRunner {
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
test(TestVector2D.class);
}
public static void test(Class<?> clazz) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
for (Method m : clazz.getDeclaredMethods()) {
Annotation testtest = m.getAnnotation(TestTest.class);
if (testtest != null) {
try {
m.invoke(null);
} catch (InvocationTargetException e) {
if (e.getCause().getClass() == Assert.AssertException.class) {
System.err.println(e.getCause().getMessage());
} else {
throw e;
}
}
}
}
}
}
Haiku
on a blind date
“So, how was your day?”
My date—a vampire—blinked twice
“We don’t reflect much”
“So, how was your day?”
My date—a vampire—blinked twice
“We don’t reflect much”