Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Linguagens Dinâmicas são Melhores para Implementar OO

Linguagens Dinâmicas são Melhores para Implementar OO

Palestra apresentada na RubyConf Brasil 2012

cassiomarques

August 30, 2012
Tweet

More Decks by cassiomarques

Other Decks in Programming

Transcript

  1. package br.com.rubyconf; public class FlyingCat implements FlyingAnimal,Feline { public void

    talk() { // implementation... } public void fly() { // implementation... } }
  2. class A { public: void foo() { cout << "calling

    A's implementation" << endl; }; };
  3. class B : public A { public: void foo() {

    cout << "calling B's implementation" << endl; } }; class C : public A { public: void foo() { cout << "calling C's implementation" << endl; } };
  4. class D : public B, public C { }; int

    main (int argc, char const* argv[]) { D d = D(); d.foo(); return 0; }
  5. teste.cpp|50 error| error: request for member ‘foo’ is ambiguous teste.cpp|26

    error| error: candidates are: void A::foo() teste.cpp|39 error| error: void C::foo() teste.cpp|33 error| error: void B::foo()
  6. class Product include Sellable include Discountable def price super -

    super * discount end end item = Product.new puts item.price # 13.5
  7. class Product end product = Product.new puts product.price # undefined

    method `price' for #<Product: 0x00000105ab7e70> (NoMethodError)
  8. ou

  9. class BaseClass # ... end class OurClass < BaseClass #

    ... end some_object = OurClass.new some_object.do_something
  10. some_object.do_something Singleton class OurClass included modules included modules BaseClass Object

    (nativo) Module Kernel (nativo) BasicObject (nativo) undefined method `do_something' for #<OurClass: 0x0000010450fe88> (NoMethodError)
  11. C++

  12. class Vehicle { public: void virtual move() = 0; void

    setColor(string _color) { color = _color; } private: string color; };
  13. class Car : public Vehicle { public: void move() {

    cout << "Moving..." << endl; } };
  14. package br.com.rubyconf; public abstract class Vehicle { private String color;

    public abstract void move(); public void setColor(String color) { this.color = color; } }
  15. package br.com.rubyconf; public class Car extends Vehicle { public void

    move() { System.out.println("Moving..."); } }
  16. Contrato informal: é preciso que a classe que inclui o

    module Enumerable defina um método each
  17. class Library include Enumerable def initialize @books = [] end

    def add_book(book) @books << book end def each @books.each { |book| yield book } end end
  18. library = Library.new library.add_book Book.new("Book 1") library.add_book Book.new("Book 2") library.add_book

    Book.new("Book 3") library.each { |book| puts book.title } # Book 1 # Book 2 # Book 3
  19. C++

  20. class Tax { public: float virtual dueValue() = 0; float

    virtual retainedValue() = 0; string virtual getName() = 0; Tax(float _value) {} protected: float value; };
  21. class Irpj : public Tax { public: Irpj(float _value) :

    Tax(_value) { this->value = _value; } float dueValue() { return value * 0.033; } float retainedValue() { return value * 0.015; } string getName() { return "IRPJ"; } };
  22. class Pis : public Tax { public: Pis(float _value) :

    Tax(_value) { this->value = _value; } float dueValue() { return 0.0; } float retainedValue() { return value * 0.0065; } string getName() { return "PIS"; } };
  23. class Invoice { public: Invoice(float _value) { value = _value;

    Irpj *irpj = new Irpj(value); Pis *pis = new Pis(value); taxes.push_back(irpj); taxes.push_back(pis); } void print() { for (unsigned int i = 0; i < taxes.size(); i++) { Tax *tax = taxes[i]; cout << tax->getName() << endl; cout << "Devido: R$" << tax->dueValue() << endl; cout << "Retido: R$" << tax->retainedValue() << endl; } } private: float value; vector<Tax*> taxes; };
  24. int main (int argc, char const* argv[]) { Invoice invoice

    = Invoice(1000.00); invoice.print(); return 0; } // IRPJ // Devido: R$33 // Retido: R$15 // PIS // Devido: R$0 // Retido: R$6.5
  25. public class Irpj implements Tax { private double value; public

    Irpj(double value) { this.value = value; } public double dueValue() { return value * 0.033; } public double retainedValue() { return value * 0.015; } public String getName() { return "IRPJ"; } }
  26. public class Pis implements Tax { private double value; public

    Pis(double value) { this.value = value; } public double dueValue() { return 0.0; } public double retainedValue() { return value * 0.0065; } public String getName() { return "PIS"; } }
  27. public class Invoice { private List<Tax> taxes = new ArrayList<Tax>();

    private double value; public Invoice(double value) { this.value = value; Irpj irpj = new Irpj(this.value); Pis pis = new Pis(this.value); taxes.add(irpj); taxes.add(pis); } public void print() { for(Tax tax : taxes) { System.out.println(tax.getName()); System.out.println("Devido: R$" + tax.dueValue()); System.out.println("Retido: R$" + tax.retainedValue()); } } }
  28. package br.com.rubyconf; public class Main { public static void main(String[]

    args) { Invoice invoice = new Invoice(1000.00); invoice.print(); } } //IRPJ //Devido: R$33.0 //Retido: R$15.0 //PIS //Devido: R$0.0 //Retido: R$6.5
  29. class Irpj include Tax def name "IRPJ" end def retained_value

    value * 0.015 end def due_value value * 0.033 end end
  30. class Pis include Tax def name "PIS" end def retained_value

    value * 0.0065 end def due_value 0.0 end end
  31. class Invoice def initialize(value) @value = value @taxes = []

    @taxes << Irpj.new(value) @taxes << Pis.new(value) end def print @taxes.each do |tax| puts tax.name puts "Devido: R$#{tax.due_value}" puts "Retido: R$#{tax.retained_value}" end end end
  32. invoice = Invoice.new(1000.0) invoice.print # IRPJ # Devido: R$33.0 #

    Retido: R$15.0 # PIS # Devido: R$0.0 # Retido: R$6.5
  33. C++

  34. class Printer { public: void print(Report report) { // ...

    } void print(Note note) { // ... } void print(Document document) { // ... } };
  35. public class Printer { public void print(Document document) { //

    ... } public void print(Note note) { // ... } public void print(Report report) { // ... } }
  36. class Printer def print(printable) case printable when Document print_document printable

    when Note print_note printable when Report print_report printable end end private def print_document(printable) # ... end def print_note(printable) # ... end def print_report(printable) # ... end end
  37. C++

  38. template <class Printable> class Printer { public: void print(Printable printable)

    { cout << "Printing a " << typeid(printable).name() << endl; } };
  39. int main (int argc, char const* argv[]) { Printer<Note> printer

    = Printer<Note>(); printer.print(Note()); return 0; }
  40. public class Main { public static void main(String[] args) {

    Printer<Document> printer = new Printer<Document>(); printer.print(new Document()); } }
  41. C++

  42. template <class Printable> class Printer { public: Printer() { printables

    = vector<Printable>(); } void print(Printable printable) { cout << "Printing a " << typeid(printable).name() << endl; } void addPrintable(Printable printable) { printables.push_back(printable); } void printAll() { for (int i = 0; i < printables.size(); i++) { print(printables[i]); } } private: vector<Printable> printables; };
  43. public class Printer<Printable> { private List<Printable> printables = new ArrayList<Printable>();

    public void addPrintable(Printable printable) { printables.add(printable); } public void print(Printable document) { System.out.println("Printing a " + document); } public void printAll() { for(Printable printable : printables) { print(printable); } } }
  44. public class Main { public static void main(String[] args) {

    Printer<Document> printer = new Printer<Document>(); Document doc1 = new Document(); Document doc2 = new Document(); printer.addPrintable(doc1); printer.addPrintable(doc2); printer.printAll(); } }
  45. class Printer def initialize @printables = [] end def add_printable(printable)

    @printables << printable end def print(printable) puts "Printing a #{printable.class.name}..." end def print_all @printables.each { |p| print p } end end
  46. printer = Printer.new doc1 = Document.new printer.add_printable doc1 doc2 =

    Document.new printer.add_printable doc2 printer.print_all
  47. printer = Printer.new doc = Document.new printer.add_printable doc1 note =

    Note.new printer.add_printable note report = Report.new printer.add_printable report foo = Foobar.new printer.add_printable foo printer.print_all
  48. C++

  49. class TotalCalculatorWithDiscount : public TotalCalculator { private: double discountPercentage; public:

    TotalCalculatorWithDiscount(double discountPercentage) { this->discountPercentage = discountPercentage; } double total(vector<LineItem> items) { double t = 0.0; for (unsigned int i = 0; i < items.size(); i++) { t += items[i].getTotal(); } return t - (t * discountPercentage/100); } };
  50. class Cart { private: vector<LineItem> items; TotalCalculator *calculator; public: Cart(TotalCalculator

    *calculator) { this->calculator = calculator; } vector<LineItem> getItems() { return items; } double getTotal(); }; double Cart::getTotal() { return calculator->total(); }
  51. TEST(Cart, ReturnsTotalValue) { MockTotalCalculator calculator; LineItem lineItem1 = LineItem(10.0, 2);

    LineItem lineItem2 = LineItem(15.0, 3); Cart cart = Cart(calculator); cart.addItem(lineItem1); cart.addItem(lineItem2); vector<LineItem> items; items.push_back(line_item1); items.push_back(line_item2); EXPECT_CALL(calculator, total(items)) .WillOnce(Return(65.00)); EXPECT_EQ(cart.getTotal(), 65.00); }
  52. public class TotalCalculatorWithDiscount implements TotalCalculator { private double percentageDiscount; public

    TotalCalculatorWithDiscount(double percentageDiscount) { this.percentageDiscount = percentageDiscount; } public double total(List<LineItem> items) { double t = 0.0; for(LineItem item : items) { t += item.getTotal(); } return t - (t * percentageDiscount/100.0); } }
  53. public class Cart { private List<LineItem> items = new ArrayList<LineItem>();

    private TotalCalculator calculator; public Cart(TotalCalculator calculator) { this.calculator = calculator; } public void addItem(LineItem item) { items.add(item); } public double getTotal() { return calculator.total(items); } }
  54. import static org.mockito.Mockito.*; public class TestCart { @Test public void

    calculatesTotalValue() { LineItem item1 = mock(LineItem.class); LineItem item2 = mock(LineItem.class); List<LineItem> items = new ArrayList<LineItem>(); TotalCalculator mockedCalculator = mock(TotalCalculator.class); items.add(item1); items.add(item2); when(mockedCalculator.total(items)).thenReturn(65.00); Cart cart = new Cart(mockedCalculator); cart.addItem(item1); cart.addItem(item2); assertEquals(cart.getTotal(), 65.00, 0.0001); verify(mockedCalculator).total(items); } }
  55. class TotalCalculatorWithDiscount def initialize(percentage_discount) @percentage_discount = percentage_discount end def total(items)

    t = items.inject(0.0) { |total, item| total += item.total } t - (t * percentage_discount / 100.0) end end
  56. class Cart attr_reader :items def initialize(calculator) @items = [] @calculator

    = calculator end def add_item(item) @items << item end def total @calculator.total items end end
  57. describe Cart do describe "#total" do it "calculates the cart's

    total" do calculator = stub item1 = stub item2 = stub calculator.should_receive(:total) .with([item1, item2]).and_return(65.00) cart = Cart.new calculator cart.add_item item1 cart.add_item item2 cart.total.should == 65.00 end end end
  58. Se você sabe o tipo, você sabe a quais contratos

    o objeto atende (quais métodos são implementados)
  59. ?