CSC/ECE 517 Fall 2010/ch6 6a PC: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 125: Line 125:
   public void mymethod() {
   public void mymethod() {


== Packages ==
== Delegation in Java ==


=== Javassist (Java Programming Assistant) ===
=== Examples of Delegation in Java ===


Javassist is a Java library providing means to manipulate the Java bytecode of an application. It provides the support for structural reflection, i.e. the ability to change the implementation of a class at runtime. [http://www.csg.is.titech.ac.jp/~chiba/javassist/] Javassist is explicit metaprogramming, in which the metalanguage is Java. It is a load-time reflective system for Java which enables Java programs to define a new class at runtime and to modify a class file when the JVM loads it. Unlike other similar bytecode editors, Javassist provides two levels of API: source level and bytecode level.
kfjskdjflsdjfldsjfl
 
If the users use the source-level API, they can edit a class file without knowledge of the specifications of the Java bytecode. They do not have to even write an inserted bytecode sequence; Javassist instead can compile a fragment of source text on line (for example, just a single statement). This ease of use is a unique feature of Javassit against other tools. One can even specify inserted bytecode in the form of source text and Javassist compiles it on the fly. On the other hand, the bytecode-level API allows the users to directly edit a class file as other editors. Thus it makes Java bytecode manipulation simple.
 
Javassist has the following applications:
* Aspect Oriented Programming:    Javassist can be a good tool for introducing new methods into a class and for inserting before/after/around advice at the both caller and callee sides.
* Reflection:    One of applications of Javassist is runtime reflection; Javassist enables Java programs to use a metaobject that controls method calls on base-level objects. No specialized compiler or virtual machine are needed.
* Remote method invocation:    Another application is remote method invocation. Javassist enables applets to call a method on a remote object running on the web server. Unlike the Java RMI, the programmer does notneed a stub compiler such as rmic; the stub code is dynamically produced by Javassist.
 
Example:
  BufferedInputStream fin = new BufferedInputStream(new FileInputStream("Point.class"));
  ClassFile cf = new ClassFile(new DataInputStream(fin));
 
A ClassFile object can be written back to a class file. write() in ClassFile writes the contents of the class file to a given DataOutputStream. ClassFile provides addField() and addMethod() for adding a field or a method (note that a constructor is regarded as a method at the bytecode level). It also provides addAttribute() for adding an attribute to the class file.
 
To examine every bytecode instruction in a method body, CodeIterator is useful. A CodeIterator object allows you to visit every bytecode instruction one by one from the beginning to the end. To otbain this object, do as follows:
 
    ClassFile cf = ... ;
    MethodInfo minfo = cf.getMethod("move");    // we assume move is not overloaded.
    CodeAttribute ca = minfo.getCodeAttribute();
    CodeIterator i = ca.iterator();
 
Other extensions are being developed to include reflective systems for C++ and Java e.g. OpenC++ and OpenJava which are extensible preprocessors based on compile-time reflection in C++ and Java respectively.
 
=== JRuby ===
 
JRuby is a complete implementation of Ruby in Java. The scripting and functional features of the Ruby language can be used by Java developers.[http://depth-first.com/articles/2006/10/24/metaprogramming-with-ruby-mapping-java-packages-onto-ruby-modules] Simple metaprogramming techniques can be  extended from  Ruby so that Java packages are mapped onto to Ruby modules. This would be something like a Ruby-Java Bridge, since JRuby can be run from any platform with a JVM.
 
Example:
Using JRuby API calling JRuby from Java
 
    import org.jruby.*;
    public class SimpleJRubyCall {
    public static void main(String[] args) {
        Ruby runtime = Ruby.getDefaultInstance();
    runtime.evalScript(“puts 1+2”);
      }
    }
 
With metaprogramming using JRuby one can
* add methods to class,
*  add instance methods
*  add to have Java classes
 
Since metaprogramming empowers the programmer to create domain specific languages(DSL), the ones created by JRuby can always leverage Java libraries to build wrapper functionalities.
e.g. Simple JRuby DSL on top of HtmlUnit
 
=== AspectJ ===
Another library worth mentioning here is AspectJ. It enforces the aspect oriented programming (AOP) approach in Java. Aspect oriented programming is a complimentary programming paradigm to object oriented programming and is used to improve the modularity of software systems. Thus, while object oriented programming is great for modeling common behavior on a hierarchy of objects, aspect oriented programming allows you to define cross-cutting concerns by adding direct semantics and can be applied across heterogeneous object models. [http://static.springsource.org/spring/docs/2.0.x/reference/aop.html] Applications of aspect oriented programming include logging, instrumenting and debugging.
 
In object oriented programs, the natural unit of modularity is the class. In AspectJ, aspects modularize concerns that affect more than one class. In addition to classes, aspect oriented programming uses 'aspects'. Aspects enable modularization of crosscutting concerns such as transaction management that cut across multiple types and objects. Thus, AspectJ package achieves metaprogramming features with more controllability.
 
AspectJ introduces declaring aspects in the statically typed language Java by using 3 key concepts -
* Join Points - well defined points in program execution
* Advice - defines additional code to be executed around join points
* Pointcut - define those points in the source code of a program where an advice will be applied
 
The core task of AspectJ's advice weaver is to statically transform a program so that at runtime it will behave according to the AspectJ language semantics. The AspectJ weaver takes class files as input and produces class files as output. The weaving process itself can take place at one of three different times: compile-time, post-compile time, and load-time. These two java files are 'woven' together by compiler i.e. the class and the aspect behavior are tied together. This is also known as 'plugging-in' the aspect. [http://oreilly.com/catalog/9780596006549]
 
Example - Simple tracing/logging
 
Consider the HelloWorld class below which implements an application that simply displays "Hello World!" on the standard output.
package helloworld;
class HelloWorld {
    public static void main(String[] args) {
            new HelloWorld().printMessage();
    } 
    void printMessage() {
            System.out.println("Hello world!");
    }
}
 
Consider another Java source file with an aspect definition as follows -
package helloworld;
aspect Trace of eachobject(instanceof(HelloWorld)) {
    pointcut printouts(): receptions(void printMessage());
    before(): printouts() {
              System.out.println("*** Entering printMessage ***");
    }
    after():  printouts() {
              System.out.println("*** Exiting printMessage ***");
    }
}
 
In above example, the Trace aspect injects tracing messages before and after method main of class HelloWorld. If one does not want tracing, one can simply leave the aspect out and plug it in as and when required.
 
In contrast to reflection[low level], AspectJ provides more carefully controlled power, drawing on the rules learned from object-oriented development to encourage a clean and understandable program structure. An aspect imposes behavior on a class, rather than a class requesting behavior from an aspect. An aspect can modify a class without needing to edit that class - also known as 'reverse inheritance'.
 
=== MetaJ ===
 
MetaJ is another package that supports metaprogramming in the Java language. A MetaJ program consists of the Java code with special metaprogramming declarations that will control how the output code is created. It uses templates and reflection. Templates are abstractions that encapsulate a program pattern written by example. Templates are translated to Java classes, so they can be accessed in the metaprogram. Accessing patterns by example inside ordinary Java programs is a major feature of MetaJ programming. [http://www.jucs.org/jucs_10_7/metaj_an_extensible_environment]
 
Language Dependency:
MetaJ comprises of a set of concepts that are independent of the base language. These are syntax trees, code references, code iterators and code templates. A framework is defined which in which features common to most languages are abstracted. This supports independence from base language. Thus, generic operations can be defined and components that are language dependent can be plugged onto it.
 
Execution Flow Representation:
 
[[Image:Meta_3.jpg]]
 
Example:
 
Template :  SampleTempl
 
package myTempl;
language = Java // base language plug­in
template #CompilationUnit SampleTempl{
#[#PackageDeclaration:pck]#
#[#ImportDeclarationList:imps]#
class SampleTempl { ... }
#TypeDeclaration:td
}
 
Instance of Template : Java Code
 
package myTempl;
import metaj.framework.AbstractTemplate;
public class SampleTempl extends AbstractTemplate{
public final Reference imps, td, pck;
... // Implementation of superclass abstract methods
}
 
Java SDK7 has added support for dynamic typing and metaprogramming and includes MetaJ implementation.
 
=== C++ Template Metaprogramming ===
 
In C++, [http://pg-server.csc.ncsu.edu/mediawiki/index.php/CSC/ECE_517_Fall_2010/ch2_S24_rm#Template_Metaprogramming static metaprogramming] is implemented with the help of reflection. The most important implementation of reflection in C++ is using the feature of run time type-identification (RTTI) [http://depth-first.com/articles/2006/10/24/metaprogramming-with-ruby-mapping-java-packages-onto-ruby-modules]. RTTI is a system that keeps information about an object's data type in memory at run time. Run-time type information can apply to simple data types, such as integers and characters, or to generic objects. Enabling RTTI in C++ allows the use of dynamic_cast<> operation, the typeid operator or exceptions [http://en.wikipedia.org/wiki/Run-time_type_information].
 
The template mechanism in C++ allows defining parametrized classes and functions. Templates together with other C++ features constitute a Turing-complete, compile-time sub- language of C++. A Turing-complete language is a language with at least a conditional and a looping construct. C++ can be considered to be a two-level language since a C++ program may contain both static code, which is evaluated at compile time, and dynamic code, which is executed at run time. Template meta-programs are the part of a C++ source that is executed during compilation. A meta-program can access information about types not generally available to ordinary programs [9].
 
Given below is an example of how to use templates for writing a common recursive factorial program:
  template<int count>
  class FACTOR{
  public:
      enum {RESULT = count * FACTOR<count-1>::RESULT};
      };
  class FACTOR<1>{
  public:
      enum {RESULT = 1};
      };
 
If we write this-
  int j = FACTOR<5>::RESULT;
 
The above line will calculate the value of 5 factorial. As we instantiate FACTOR<5> the definition of this class depends on FACTOR<4>, which in turn depend on FACTOR<3> and so on. The compiler needs to create all these classes until the template specialization FACTOR<1> is reached. This means the entire recursion is done by the compiler during compile time and it uses the result as if it is a constant.


= Conclusion =
= Conclusion =

Revision as of 14:08, 15 November 2010

Delegation-based programming languages

" I do not care how it is done, or who is it assigned to. If something is understood to be placed in the hands of another party, it is delegation " - 'Anonymous'

Introduction

Dictionary defines delegation as the assignment of authority and responsibility to another person to carry out specific activities.In programming context it is nothing different. It is basically entrusting an action to another agent. This term was initially introduced by Henry Lieberman in his 1986 paper "Using Prototypical Objects to Implement Shared Behavior in Object-Oriented Systems". [1] He defines delegation in object oriented languages as a programming language feature making use of the method lookup rules for dispatching so-called self-calls.

The above diagram depicts that a message receiver is asking another object (message holder) to do something on its behalf which may delegate it to someone and so on and so forth

Delegation

Delegation, is also referred to as aggregation,consultation, or forwarding. In delegation one class may contain an instance of another class, and delegate some responsibility to that class. This is also referred to as the has-a relationship. Aggregation should not be confused with composition. Both aggregation and composition are used to describe one object containing another object, but composition implies ownership [2]. Aggregation is more general and doesn't imply any responsibilities for memory management. A class which contains other classes is called a composite class, while a class being contained is called a composited or composed class [3].Delegation is a very powerful reuse technique. The provides run time flexibility. It is also called dynamic inheritance.[4]

Delegation can be implemented in many programming languages like Ada, Aikido, C, C#, C++, Common Lisp, D, E, Go, J, Java, JavaScript, Logtalk, Objective-C,Oz, Perl,Perl 6, PHP, PicoLisp, Pop11, Python, Ruby, TCL, Vorpal [5]

Example in a Java like language:

class Delegate
{
    void doSomething()
    {
        // "this" is also known as "current", "me" and "self" in other languages
        this.callMe()
    }
    void callMe() 
    {
        print("I am Delegate")
    }
}
class Delegator
{
    private Delegate d;  // delegationlink
    public Delegator(Delegate d)
    {
        this.d = d;
    }
    void doSomething() {
        d.doSomething() // call doSomething() on the Delegate instance
    }
    void callMe() {
        print("I am Delegator")
    }
}
d = new Delegate()
b = new Delegator(d) // establish delegation between two objects


Here calling b.doSomething() will result in "I am Delegate" being printed, since class Delegator "delegates" the method callMe() to a given object of class Delegate.

Delegation vs Inheritance

Inheritance and delegation are used in different situations in object oriented programming. These two are different concepts and it would be incorrect to use them interchangeably.

Delegation:

  • Delegation takes place at run-time
  • Since it takes place at run-time, it can even be removed at run-time
  • Cannot guarantee static type-safety (By using interfaces, delegation can be made more flexible and typesafe)

Inheritance:

  • Inheritance is restricted to compile time
  • Since it targets type rather than instances, it cannot be removed/changed at runtime
  • Inheritance ca be statically type-checked


Hints to use Inheritance

  • Inheritance is used to create sub-categories of objects
  • Mostly identified in 'is-a' relationships between objects
  • Inheritance is used when two objects are of the same type but one of the objects may need to have its own customized functionality. The child object just inherits from the parent and writes its own implementation of the feature it needs extra.
  • Inheritance can be implemented on objects of the same type only.

Hints to use Delegation

  • Delegation is used when two objects aren't of the same type but one has methods and attributes that the other wants to use internally instead of writing its own implementation
  • Identified as 'as-a' relationships where the type of included object may change during runtime.
  • Delegation is used when methods implementation needs to be handled by some other class within the parent tree. The class that will handle the method isn't known at compile time.
  • Code execution within objects needs to be determined dynamically.

Situations where you can use delegation

djfsjdflksjflkjflkjflkjflkj

Delegation Design Pattern

kfjlskfjlksdjflkdjjjjjjjlkjlkjf Give examples from various programming languages

Delegation in Ruby

dfkjdlfjlfjljflsdj

Example of delegation in Ruby

ksdjflkdsjflk


  • Single-Element: Single-element, or single-value type, annotations provide a single piece of data only. This can be represented with a data=value pair or, simply with the value (a shortcut syntax) only, within parenthesis.

Example:

 public @interface MyAnnotation
 {
   String doSomething();
 } 

Usage:

 @MyAnnotation ("What to do")
 public void mymethod() {
  ....
 } 
  • Full-value or multi-value: Full-value type annotations have multiple data members. Therefore, you must use a full data=value parameter syntax for each member.

Example:

 public @interface MyAnnotation {
   String doSomething();
   int count; String date();
 } 

Usage:

 @MyAnnotation (doSomething="What to do", count=1,
             date="09-09-2005")
 public void mymethod() {

Delegation in Java

Examples of Delegation in Java

kfjskdjflsdjfldsjfl

Conclusion

Dynamically typed languages are best suited to provide support for metaprogramming due to their inherent nature of easily overcoming distinction between code and data e.g. Lisp provides this feature of interchangeability. Code and data are both represented in Lisp as lists, so any list can easily be treated as either code or data. It’s simple, therefore, to manipulate code as data, and then execute it – either via EVAL or by returning it as the result of a macro expansion. [3]

Thus, statically typed languages achieve metaprogramming using various techniques and tools to achieve the level of flexibility that dynamic languages provide immanently.

References and Notes

Further Reading