CSC/ECE 517 Fall 2011/ch1 1i cl: Difference between revisions

From Expertiza_Wiki
Jump to navigation Jump to search
Line 339: Line 339:
==<b>Ruby</b>==
==<b>Ruby</b>==
===<i> General</i> ===
===<i> General</i> ===
Methods are the cornerstone of object-oriented programming, and since Ruby is a pure-OO language (everything is an object), methods are inherent to the nature of Ruby. Object is the parent class of all classes in Ruby. Its methods are therefore available to all objects unless explicitly overridden. Method can be reimplementation in Ruby via Module and Random Parameter


===<b>Module</b>===
===<b>Module</b>===

Revision as of 20:41, 7 September 2011

Introduction

In O-o languages Object-oriented languages, method is a subroutine that associates with the the class and defines the behaviors performed by the instances of the class. A ancestor class may has its descendant classes which inherit all its methods' propertiess(name,return type,etc). Method reimplementation is required when the decendent class needs to change the behavior of a method which was already implemented by the ancestor class, and it is more efficient to do so other than writing a new method. In different O-o languages, the ways to require or allow a class to reimplement methods are very different. So it is important for us to know how different languages handle the reimplementation and what are the advantages and disadvantages of them.

Reimplementation in different O-o languages

C++

General

There are two ways that C++ can re-implement methods in descendant classes, one is Overridden method, which is very similar with Java in overriding and overloading. The other is to re-implement methods by virtual function. Although the characteristic of virtual function can also be found in other languages such as Java, but in C++, virtual function is an important way to achieve polymorphism in C++.


Overridden


Quite similar to Java, the overridden in C++ has features as follows:

1, the functions should be in different classes, class A and subclass of A.

2, the name of functions should be the same.

3, the parameters of functions should be the same.

4, keyword” virtual” should be appeared in base class.

An example is explained as follows:

class Dog {
public:
	Dog(char* nm, int s):name(name),size(s){}
	virtual void print() const;
private:
	char* name;
	int size;
};

void Dog::print() const{  // print() method of base class
	std::cout<<”Name = ” << this->name << “; Size = ” << this->size;
}

class Dog_large: public Dog {
public:
	Dog_large(char * nm, int s, int t) : Dog(nm,s), type(t) {}
	virtual void print() const;

private:
	int type;
};

void Dog_large::print() const{
	Dog::print();
	Std::cout<<”; Type = ” << this-> type;
}

The main method will call the print method in class Dog and class Dog_car separately.

Int main(int argc, char** argv) {
	Dog dog_test(“Bart”, 11);
        Dog_test.print();
        //outputs:
        //Name = Bart; Size = 11

        Dog_large dog_large_test(“Lufu”,”17”,”11”);
        //the pointer to the most overridden method in the vtable in on Dog_car::print
        dog_large_test.print();// but this call does not illustrate overriding
        static_cast<Dog&>(dog_large_test).print(); // this one does
        //output
        // Name = Bart; Size = 11;Type = 11
}

Virtual method


To define a virtual method in C++, the virtual keyword should be added before the declaration of the method. This method’s behavior can be changed or we say overridden within an inheriting class by a function with the same signature. Although virtual method also exists in other programming language, this is an important way to achieve polymorphism in C++.


#include <iostream>
#include <vector>

class Animal {
    public:
        virtual void eat() const { 
            std::cout << "I eat like a generic Animal." << std::endl; 
        }
        virtual ~Animal() { 
        }
};
 
class Wolf : public Animal {
    public:
        void eat() const { 
            std::cout << "I eat like a wolf!" << std::endl; 
        }
        virtual ~Wolf() { 
        }
};
 
class Fish : public Animal {
    public:
        void eat() const { 
            std::cout << "I eat like a fish!" << std::endl; 
        }
        virtual ~Fish() { 
        }
};
 
class GoldFish : public Fish {
    public:
        void eat() const { 
            std::cout << "I eat like a goldfish!" << std::endl; 
        }
        virtual ~GoldFish() { 
        }
};
 
class OtherAnimal : public Animal {
        virtual ~OtherAnimal() { 
        }
};
 
int main() {
    std::vector<Animal*> animals;
    animals.push_back(new Animal());
    animals.push_back(new Wolf());
    animals.push_back(new Fish());
    animals.push_back(new GoldFish());
    animals.push_back(new OtherAnimal());
 
    for (std::vector<Animal*>::const_iterator it = animals.begin(); it != animals.end(); ++it) {
        (*it)->eat();
        delete *it;
    }
 
    return 0;
}

Output with the virtual function Template:Cpp:

I eat like a generic Animal.
I eat like a wolf!
I eat like a fish!
I eat like a goldfish!
I eat like a generic Animal.

Output, if Template:Cpp were not declared as virtual:

I eat like a generic Animal.
I eat like a generic Animal.
I eat like a generic Animal.
I eat like a generic Animal.
I eat like a generic Animal.


What's different of "virtual" in C++


In C++, almost everything that has relevant to polymorphism is done by keyword “virtual”. In addition to this, virtual has other two functions.

Virtual base class

In base class A there are two subclass, B and C. D is inherited from B and C, but in D, there are two “A” as duplicate. Virtual base class is introduced to solve this problem. Shown as the example:

class B :virtual public A class C :virtual public A class D: public B, public C

Abstract class

Any class include: pure virtual function is called abstract class. Pure virtual function means no functionality in a function, and with a mark ‘=0’, as examples below:

void virtual foo() = 0;


The Virtual in C#


keyword” virtual ” can invoked virtual methods in both C++ and C#, these methods can be overridden in subclasses. However, it is in C# that the keyword “abstract” be introduced, to invoke virtual method without function. In C++, this job can be done by keyword” virtual”, we can it “pure virtual method”, class included pure virtual method can be called as “abstract class”.

In C#, Keyword “Virtual” can be added to “properties” and “methods” to indicate that the method in subclass can be rewrite. In general, keyword virtual in C# has been considerably impaired. In C#, the job in relevant of polymorphism has been taken by keyword” interface ” and “ abstract”, which was previously done by “virtual” in C++.

Java

General

In Java, we can use variaty of approaches to do the reimplementation. We still have approaches like Overridden Methods and Virtual Methods the same as what we have in C++, while there are some other convinient approaches such as Abstract Methods and Overloading Methods which C++ doesn't support. And we can put @override tag on top of a overriding mothed to have the complier check if the method is succesfully overridden.

Overriding

If a sub class inherited a method from the super class, as long as the method is not marked as final, the sub class can do overriding to reimplement the method and change the functionality of that method. But the overriding method must follow the requirement of the super class's method.

Here is an example.

class human{

   public void move(){
      System.out.println("Human can only walk");
   }
}

class superman extends human{

   public void move(){
      System.out.println("Superman can fly!");
   }
}

public class Test{

   public static void main(String args[]){
      human Li = new human();
      human Xue = new superman(); 

      Li.move();
      Xue.move();
   }
}

And the output result should be

Human can only walk
Superman can fly!

When you create Xue as an instance of superman class, its method move() will automatically override the its super class human's method with the same name.

In above example, Xue is defined as a type of human but it still can fly, that is because in compile time, it only checks the reference type, while in runtime, JVM knows the type of the object and will run the correct method which belongs to it.

Virtual Methods

In Java, all the method that are not marked as final are default virtual methods. So although we do have the idea of virtual methods in Java, actually it goes nothing different with the override methods.

Overloading

In Java, methods with the same name are allowed as long as they take different parameters. It is very convenient to have such kind of function because sometimes our method needs to take different types of parameters, and we don't want to have a list of different method names to confuse the users.

For example, while we have this method in the ancestor class

public int min(int n1, int n2) {
   int m;
   if (n1 < n2)
      m = n1;
   else
      m = n2;

   return m; 
}

We can still have this method in the descendant class

public int min(double n1, double n2){
   int m;
   if (n1 < n2)
      m = n1;
   else
      m = n2;

   return m; 
}

The program will invoke the right method depending on the type of the input.

But one important thing to remember is, only methods with different list of parameters are allowed to have the same names. We can not have overloaded methods based on different return types or modifiers. Different

Abstract Methods

In Java, when you want to define the structure of a class, and leave the implementation to its child classes, you can use a abstract class. In the abstract class, all the methods are abstract methods. They only have method signatures, but no method bodies. The child class can implement the abstract class and all the methods it has.

There are two important notes: 1. Once a method is declared as abstract method, its class must be declared as a abstract class. 2. The child classed must either override the methods or declare them as abstract themselves.

Here is the example, we defined a abstract class Shape

abstract class Draw {

	public String color;
	public Draw() {
	}
	public void setColor(String c) {
		color = c;
	}
	public String getColor() {
		return color;
	}
	abstract public double area();
}

Then we can define a sub class Point which extends Draw

public class Point extends Draw {

	static int x, y;
	public Point() {
		x = 0;
		y = 0;
	}
	public double area() {
		return 0;
	}
	public double perimeter() {
		return 0;
	}
	public static void print() {
		System.out.println("point: " + x + "," + y);
	}
	public static void main(String args[]) {
		Point p = new Point();
		p.print();
	}
}

When the sub class implements the super class, it must implement all of the methods that the super class has. It is not allowed to leave any abstract method not implemented, and once there is a abstract method in the sub class, it makes the sub class itself a abstract class.

Ruby

General

Methods are the cornerstone of object-oriented programming, and since Ruby is a pure-OO language (everything is an object), methods are inherent to the nature of Ruby. Object is the parent class of all classes in Ruby. Its methods are therefore available to all objects unless explicitly overridden. Method can be reimplementation in Ruby via Module and Random Parameter

Module


To better understand module in the reimplementation in sub-class of Ruby, first an example is given as follows:

module M
	def say
		puts "Hello World"
	end
end

class A
	include M
end

class B<A
end

obj=B.new
obj.say

It is very clear that M is a module include method say, A is a class of module M, B inherited from A. When invoke method say, Ruby will search this method in class B, if can’t find, Ruby will continue search in father-class A, if the method is found, run it, if still not, continue this search from Object class and Kernel, until found or error.

The introduction of module is to add flexibility to Ruby, make reimplementation possible. Since every class in Ruby inherited and only inherited from one class, which is different from multi-inherited of C++, it reduced the complexity. And we can also achieve multi-inherit by mixin mechanism.


Random Parameter



Method with parameters in sub-class can be modified by random parameter by adding a * in ahead of parameters. An example is given below:

def max(first, *rest)
	max=first
	rest.each{|x|max=x if x>max}
	max
end

We can call this method, we got the output of

data = [3,2,1] m=max(*data)

output:

first =3, rest=[2,1] =>3


But if

m=max(data)

Output:

first= [3,2,1], rest=[] =>[3,2,1]

Advantages

C++

The two ways of reimplantation can be achieve by keyword "virtual" , which also serve as a very useful and powerful tool in many other aspects, such as Virtual base class, and Abstract class, especially in polymorphism of C++.

Java

Ruby

Disadvantages

C++

Some times the variety use of keyword "virtual" may lead to confusion and misunderstanding

Java

Ruby

Conclusion

Reference

"Tutorials Point.com" http://www.tutorialspoint.com/java/index.htm

"Java Beginner.com" http://www.javabeginner.com/learn-java/java-abstract-class-and-interface

http://en.wikipedia.org/wiki/Virtual_function

http://www.vckbase.com/document/viewdoc/?id=950

http://en.wikipedia.org/wiki/C%2B%2B

http://www.cnblogs.com/realyan/archive/2011/07/13/2105801.html

http://helloxuweifu.iteye.com/blog/1165745

http://qa.taobao.com/?p=11648

See also

The JavaTM Tutorials http://download.oracle.com/javase/tutorial/index.html