AB2015’de vereceğimiz “Python ile Oyun Programlamaya Giriş” kursuna hazırlık yaparken, kullanacağımız kütüphanede (Python SFML) bir hata keşfetmiştim. İki tane Rectangle nesnesinin birbiriyle kesişip kesişmediğini gösteren bir metot hatalı olara çalışıyordu. Normalde Github’daki repoda bu hata hemen kapatılmıştı fakat Ubuntu’daki 1.3 sürümünde bu hata halen daha devam ediyor. Launchpad üstünden yaptığım hata bildirimi ve düzeltmesine rağmen halen yeni haliyle paketlenmeyince, ben de daha farklı bir yönteme girişeyim dedim. Hata bildirimi burada:
https://bugs.launchpad.net/ubuntu/+source/python-sfml/+bug/1400906
Normalde sitesinde de hemen bir çözüm yolu önermişler, hatanın farkında olup:
http://en.sfml-dev.org/forums/index.php?topic=11436.0
Ama bu kütüphaneyi derlemesi inanılmaz zahmetli, bu yüzden mevcut depoyu kullanmak daha akıl karı duruyor. Tabi hatalı olan metodu override etmek için Ruby’deki açık sınıf sistemini düşündüm başta, zira Ruby’de bu sistem tek kelimeyle şahane işliyor. Örneğin String sınıfının içerisindeki, to_sym metodunu şu şekilde kolayca override edebiliyoruz:
1 2 3 4 5 6 7 | class String def to_sym "Sembol membol yok sana!" end end "naber".to_sym => "Sembol membol yok sana!" |
Aynısını Python’da yapmak için, yani kalıtım yapmadan, nasıl bir yol izlerim derken şöyle bir şey keşfettim, Ruby’deki sisteme göre başta kolay gözükse de aslında biraz daha zor. Basit, örnek bir sınıf tanımlayarak bakalım:
1 2 3 4 5 6 7 8 9 | class Kitap: def __init__(self, isim): self.isim = isim def bilgi(self): print("Kitabın adı: {0}".format(self.isim)) Kitap("Otostopçunun Galaksi Rehberi").bilgi() # Çıktısı=> Kitabın adı: Otostopçunun Galaksi Rehberi |
Kitap sınıfındaki bilgi metodunu override etmek istediğimizde şöyle bir yöntem gerekecek:
1 2 3 4 5 6 7 | def yeni_bilgi(self): print("Bu şahane kitabın adı: {0}".format(self.isim)) Kitap.bilgi = yeni_bilgi Kitap("Otostopçunun Galaksi Rehberi").bilgi() # Çıktısı=> Bu şahane kitabın adı: Otostopçunun Galaksi Rehberi |
Bunlara bakınca zor gibi gelmiyor evet ama C eklentileri (extension) kullanan bir kütüphane, örneğin Cython’la geliştirilen Python SFML kütüphanesi, bu tarz metot override etmeye izin vermiyor ve şu hatayı veriyor:
1 | TypeError: can't set attributes of built-in/extension type "..." |
Bunun için çözüm ise forbiddenfruit adlı bir Python kütüphanesi. Doğrudan pip ile kurulabiliyor:
1 | $ sudo pip2 install forbiddenfruit |
Ardından proje içersisinde kütüphanein içerisindeki curse metodunu kullanarak istediğimiz metodu override edebiliyoruz, C ile derlenmiş olsa bile.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import sfml as sf from forbiddenfruit import curse def new_intersects(obj, rectangle): l, t, w, h = rectangle rectangle = sf.Rectangle((l, t), (w, h)) left = max(obj.left, rectangle.left) top = max(obj.top, rectangle.top) right = min(obj.right, rectangle.right) bottom = min(obj.bottom, rectangle.bottom) if left < right and top < bottom: return sf.Rectangle((left, top), (right - left, bottom - top)) curse(sf.Rectangle, 'intersects', new_intersects) a = sf.Rectangle((0, 0), (100, 100)) b = sf.Rectangle((550, 550), (100, 100)) print a.intersects(b) |