Siêu thị PDFTải ngay đi em, trời tối mất

Thư viện tri thức trực tuyến

Kho tài liệu với 50,000+ tài liệu học thuật

© 2023 Siêu thị PDF - Kho tài liệu học thuật hàng đầu Việt Nam

Rails for Java Developers phần 4 ppt
MIỄN PHÍ
Số trang
32
Kích thước
213.7 KB
Định dạng
PDF
Lượt xem
1764

Rails for Java Developers phần 4 ppt

Nội dung xem thử

Mô tả chi tiết

MIXINS 91

def add_employee(employee)

employee.employer.remove_employee(employee) if employee.employer

self.employees << employee

employee.employer = self

end

def remove_employee(employee)

self.employees.delete employee

employee.employer = nil

end

end

Classes such as BusinessPerson can then pick up Employer functionality

by calling include Employer:

Download code/rails_xt/samples/business_person.rb

class BusinessPerson < Person

include Employer, Employee

end

Now the BusinessPerson class can call any Employer methods:

irb(main):001:0> require 'business_person'

=> true

irb(main):002:0> boss = BusinessPerson.new("Justin", "Gehtland")

=> #<BusinessPerson:0x54394 @first_name="Justin", @last_name="Gehtland">

irb(main):003:0> drone = BusinessPerson.new("Stu", "Halloway")

=> #<BusinessPerson:0x4f9d4 @first_name="Stu", @last_name="Halloway">

irb(main):004:0> boss.add_employee(drone)

=> etc.

The fact that include is a method call has interesting implications. The

object model is not static, and you could choose to have BusinessPerson

include Employer under some circumstances and not others. In fact,

you can make object model decisions per instance instead of per class.

The extend method works like include but on a specific instance. So, a

specific person could become an Employer at runtime:

irb(main):001:0> require 'business_person'

=> true

irb(main):002:0> p = Person.new("Stu", "Halloway")

=> #<Person:0x5490c @first_name="Stu", @last_name="Halloway">

irb(main):003:0> class <<p; ancestors; end

=> [Person, Object, Kernel]

irb(main):004:0> p.extend Employer

=> #<Person:0x5490c @first_name="Stu", @last_name="Halloway">

irb(main):005:0> class <<p; ancestors; end

=> [Employer, Person, Object, Kernel]

The variable p starts life as a “plain old Person” with class ancestors

[Person, Object, Kernel]. The extend Employer call turns p into an Employer

as well, and the ancestor list changes appropriately. The odd-looking

FUNCTIONS 92

statement class <<p accesses the singleton class of p. A singleton class singleton class

might better be known as an instance-specific class. You have modified

the inheritance hierarchy of p, so it is not “just a Person.” It now has its

own instance-specific class, which tracks its unique ancestors list.

3.9 Functions

Strictly speaking, neither Java nor Ruby has functions. Nevertheless,

it is reasonable to talk about functions: Sometimes a function can be

handy, and both Java and Ruby have important idioms for these situ￾ations. Consider this simple example, a program that reads a bunch of

lines from stdin and then prints them back sorted:

Download code/java_xt/src/SortWords.java

import java.io.*;

import java.util.*;

public class SortWords {

public static void main(String[] args)

throws IOException {

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

List al = new ArrayList();

String line = null;

while (null != (line = br.readLine())) {

al.add(line);

}

Collections.sort(al);

System.out.println("sorted:");

for (Iterator it = al.iterator(); it.hasNext();) {

System.out.println(it.next());

}

}

}

Here is an equivalent program in Ruby:

Download code/rails_xt/samples/sort_words.rb

puts readlines.sort.unshift("sorted:\n").join

Both programs produce output like this:

$ ruby samples/sort_words.rb

quick

brown

fox (close stdin here with Ctrl-D or equivalent...)

sorted:

brown

fox

quick

FUNCTIONS 93

Fine so far. But what if you wanted to sort by some other criteria, such

as word length or preponderance of vowels? If you can imagine lots of

different criteria, or if new criteria might turn up at runtime, you will

quickly want a general solution that might look like this:

Collections.sort(al, sortByWordLength);

In English, this might read as “Sort the collection al using the function

sortByWordLength( ) to compare words.” And, in fact, Java works exactly

like this—except without the f-word.4

Instead of using a function, you

can build a function-like object out of pieces you do have: interfaces

and inheritance. Java’s collections API provides a Comparator interface:

public interface Comparator {

int compare(Object o, Object o1);

}

You can write your own class that implements Comparator and com￾pares strings by some criteria you care about. Return a negative num￾ber if the first object is lesser, 0 if the objects are equal, and a positive

number if the second object is the lesser of the two. Creating an entirely

new class just to specify a sort order is often a big diversion, so Java

provides a shortcut called the anonymous inner class. Using an anony￾mous inner class, you can specify the sort “function” directly inside the

call to sort:

Download code/java_xt/src/SortWords2.java

Collections.sort(al, new Comparator() {

public int compare(Object o, Object o1) {

return ((String)o).length() - ((String)o1).length();

}

});

Java’s anonymous inner classes, when used in this way, are functions

in everything but name. Having an ordering function return negative, 0,

or positive is common to Java and Ruby (and many other languages).

In Ruby, you can use a block to implement the sort “function”:

Download code/rails_xt/samples/sort_words_2.rb

sorted = readlines.sort {|x,y| x.length-y.length}

puts "sorted:\n#{sorted.join}"

The block syntax (curly braces or do...end) is the same syntax you exam￾ined in Section 2.4, Collections and Iteration, on page 47. In Ruby, you

will typically use a block whenever you want to “pass a function to a

4. The seven-letter f-word. Shame on you.

Tải ngay đi em, còn do dự, trời tối mất!