Pages

Sunday, December 30, 2012

SOLID principle in OOP programming

http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)

  • Single responsibility principle (SRP)
    • An object should have only a single responsibility.
  • Open/closed principle (OCP)
    • Software entitles … should be open for extension, but closed for modification.
  • Liskov substitution principle (LSP)
    • Objects in a program should be replaceable with instance of their subtypes without altering the correctness of that program.
  • Interface segregation principle (ISP)
    • Many client specific interfaces are better one general purpose interface
  • Dependency inversion principle (DIP
    • Do not depend upon concretions. One should depend upon abstraction.

Closure in Java using Anonymous Inner Class - example

Java doesn't support closure, but using Anonymous Inner Class, we can experience closure in Java.

Here is the code.
class Action {
	public void doAction() {
		System.out.println("Hello, world");
	}
}

class A {
	public void doStuff(Action a)
	{
		a.doAction();
	}
    public void method() {
        final int i = 0;

        doStuff(new Action() {
            public void doAction() {
                System.out.println(i);   // or whatever
            }
        });
    }
}

class Closure {
	public static void main(String[] args) {
		new A().method();
	}
}
You should be careful that the local variable in the method() method should be final in order to prevent this error message.

Closure.java:17: error: local variable i is accessed from within inner class; needs to be declared final System.out.println(i); // or whatever ^ 1 error

Instead of giving closure function to doStuff() method, anonymous inner class is given. In its implementation, doStuff() uses methods in A class as if it's closure functions. You can give different code block to doStuff() if necessary.

Compared to python example or lisp example, Java needs full support closure support to make the code simpler and easier to read.

References

Closure in Lisp - example

This is a code that I borrowed from the book Practical Common Lips for closure in Lisp.
(defun artist-selector (artist)
  #'(lambda (cd) (equal (gets cd :artist) artist)))
In the code, artist-selector returns a closure that closes a variable "artist" over it. We can use this closure as a parameter to "select" function. Lisp supports high order function decades ago to enable it possible. "*db*" is a global variable.
(defun select (selector-fn)
  (remove-if-not selector-fn *db*))
The usage of "select" method is as follows. You can create another closure with different parameter to the "artist-selector" function.
(select (artist-selector "Dixie Chicks"))

References

Closure in Python - example

Closure is a "function (code block)" with a "referencing environment". I interpret it as a function pointer with free variables. In Python terms, a variable defined in an enclosing function is a free variable inside any nested functions.
In this example, printer is a closure as it points to a code block with a free variable of "msg". The variable msg is closed over the printer() function.
def make_printer(msg):
    def printer():
        print msg
    return printer

printer = make_printer('Foo!')
printer()
This printer method is not a closure but nested function, as in this case "msg" variable is nothing but a local variable that is not "closed".
def make_printer(msg):
    def printer(msg=msg):
        print msg
    return printer

printer = make_printer("Foo!")
printer() # "Foo!"
printer("Hello") # --> "Hello"

References

Polymorphism in OOP

Polymorphism in OOP is the ability of objects belonging to different types to respond to method, filed, or property calls of the same name. The caller doesn't have to know the type of the callee so that the exact behavior is determined at run-time.

For strong type languages, polymorphism usually means that type A derives from type B or C, In weakly typed languages types are implicitly polymorphic: duck typing allows polymorphism without inheritance.

There are some disputes whether overloading and overriding is a part of polymorphism.
  • Wikipedia explains they are not the same. (Polymorphism is not the same as method overloading or method overriding.1 Polymorphism is only concerned with the application of specific implementations to an interface or a more generic base class.)
  • Some of OOP books explain "method overloading" as an example of polymorphism.
  • This paper explains overloading as a part of polymorphism
  • This post explains that overriding is a part of polymorphism, whereas overloading is not.

Generic programming is also known as "parametric polymorphism".

References

  1. Polymorphism in object-oriented programming
  2. OBJECT.__class__ is CLASS and "isinstance(OBJECT, CLASS)" for polymorphism in python
  3. Duck typing
  4. Function overloading
  5. Method Overriding
  6. Is Method Overloading considered polymorphism?
  7. Polymorphism vs Overriding vs Overloading

OBJECT.__class__ is CLASS and "isinstance(OBJECT, CLASS)" for polymorphism in python

The "is" operator in Python compares the two values before and after to check if they point to the same object. Whereass the "is instance" checks if the first parameter (object) is an instance of the second parameter(class).
As a result "dog.__class__ is Animal" returns False, "isinstance(dog, Animal)" returns True.
class Animal:
    pass
    
class Dog (Animal):
    pass
    
dog = Dog()

print dog.__class__ is Animal
print isinstance(dog, Animal)
False True

Things to consider

For C# programmer, this is confusing as "is" operator in C# works as "ins instance" of Python.
In python idiom, you are not encouraged to use type-checking, instead use duck typing instead. In short, you just execute if an object can quack or not instead of checking an object is an instance of a duct that quacks.
class Duck(object): 
    def quack(self):
        print "QUACK!!!"

class DonaldDuck(object): 
    def quack(self):
        print "quack!"


def canQuack(duckType):
    duckType.quack()


duck = Duck()
donaldDuck = DonaldDuck()
canQuack(duck)
canQuack(donaldDuck)

References

How does polymorphism work in Python?

XML file generation using Python's ElementTree

Introduction

When we want to generate XML file from whatever python data structure, ElementTree might be the easiest solution. For example, when we want to transform a list of list . pairList = [ ["A.txt", "B.txt"] … ] into XML format. <root>
<node fileA="A.txt" fileB="B.txt" />
<node ... />
</root>
</code>

Code

We can implement the code as follows.
import xml.etree.ElementTree as ET

root = ET.Element('root')
for pairs in self.pairList:
    #print pairs
    testa = pairs[0]
    testb = pairs[1]
            
    child = ET.Element('node')
    child.attrib['fileA'] = testa
    child.attrib['fileB'] = testb
    root.append(child)
            
file = open(filePath, 'w')

#Create an ElementTree object from the root element
ET.ElementTree(root).write(file)

Explanations

The API names of ElementTree is pretty straightforward. For getting (or creating) an element, you need to use xml.etree.ElementTree.Element (ET.Element when you import with the name ET) API the tag name as a parameter. When you make the element, you can just append (it's also the API name python uses) the newly generated element as a children of the parent element.

You just keep creating the hierarchy using ET.Element() static and append() API.

The element has "attrib" dictionary to store the attributes of the node.

For writing the result into an XML file, you select the root, and use the write method to print out the XML.

Reference

  1. Python ElementTree XML Tutorial
  2. Processing XML in Python with ElementTree