How to override a field in a base class with a property in a derived class?

I have a base class that uses a field:

class Base(object): def __init__(self, member): self.member = member 

And a derived class that would like to promote this property and add some kind of behavior:

 class Derived(Base): @property def member(self): return super(Derived, self).member @member.setter def member(self, value): print "intercepting setter" super(Derived, self).member = value 

However, this incorrectly delegates the base class:

 >>> d = Derived(0) intercepting setter Traceback (most recent call last): File "<pyshell#8>", line 1, in <module> d = Derived(0) File "<pyshell#3>", line 3, in __init__ self.member = 2 File "<pyshell#6>", line 9, in member super(Derived, self).member = value AttributeError: 'super' object has no attribute 'member' 

How can I do it?

+4
source share
2 answers

You are trying to access super member as if it were a class attribute. Try:

 class Derived(Base): @property def member(self): print "intercepting getter" return self._member @member.setter def member(self, value): print "intercepting setter" self._member = value 
+2
source

I think moving a member to ownership is the right way to do this. This is similar to having an int member in the database and changing it to a method in a derived class. Or like a regular method and its change in a static or class method in the heir. I guess this just violates the concept.

You have several options for solving the problem.

I am. What about introducing a property to another (similar) name, which then transfers all access to the inherited original name? It would be very simple, would not break anything inherited from the base class. But this also will not allow to intercept access to the source element (performed in the base class or in any case).

II. Replace the legacy item completely. It simply means storing the value in another member and completely creating the property from scratch. Then let him access the repository of the original:

 class Base(object): def __init__(self, member): self.member = member def baseAccess(self): return self.member class Derived(Base): @property def member(self): print "getter", return self.memberStore @member.setter def member(self, value): print "setter", self.memberStore = value b = Base(24) print "Base(24)" print "b.member", b.member print "b.baseAccess()", b.baseAccess() d = Derived(23) print "Derived(23)" print "d.member", d.member print "d.baseAccess()", d.baseAccess() b.member = 43 print "b.member = 43" print "b.member", b.member print "b.baseAccess()", b.baseAccess() d.member = 42 print "d.member = 42" print "d.member", d.member print "d.baseAccess()", d.baseAccess() 

This is the conclusion:

 Base(24) b.member 24 b.baseAccess() 24 setter getter Derived(23) d.member getter 23 d.baseAccess() getter 23 b.member = 43 b.member 43 b.baseAccess() 43 setter d.member = 42 d.member getter 42 d.baseAccess() getter 42 

So, all interceptors are duly taken into account.

+1
source

Source: https://habr.com/ru/post/1481912/


All Articles