#: c07:Adapter.py
# Variations on the Adapter pattern.

class WhatIHave:
  def g(self): pass
  def h(self): pass

class WhatIWant:
  def f(self): pass

class ProxyAdapter(WhatIWant):
  def __init__(self, whatIHave):
    self.whatIHave = whatIHave

  def f(self):
    # Implement behavior using 
    # methods in WhatIHave:
    self.whatIHave.g()
    self.whatIHave.h()

class WhatIUse:
  def op(self, whatIWant):
    whatIWant.f()

# Approach 2: build adapter use into op():
class WhatIUse2(WhatIUse):
  def op(self, whatIHave):
    ProxyAdapter(whatIHave).f()

# Approach 3: build adapter into WhatIHave:
class WhatIHave2(WhatIHave, WhatIWant):
  def f(self):
    self.g()
    self.h()

# Approach 4: use an inner class:
class WhatIHave3(WhatIHave):
  class InnerAdapter(WhatIWant):
    def __init__(self, outer):
      self.outer = outer
    def f(self):
      self.outer.g()
      self.outer.h()

  def whatIWant(self): 
    return WhatIHave3.InnerAdapter(self)

whatIUse = WhatIUse()
whatIHave = WhatIHave()
adapt= ProxyAdapter(whatIHave)
whatIUse2 = WhatIUse2()
whatIHave2 = WhatIHave2()
whatIHave3 = WhatIHave3()
whatIUse.op(adapt)
# Approach 2:
whatIUse2.op(whatIHave)
# Approach 3:
whatIUse.op(whatIHave2)
# Approach 4:
whatIUse.op(whatIHave3.whatIWant())
#:~