Load child class from base class - oop

I have a base class BaseClass with multiple subclasses SubClass1, SubClass2. In practice the program only works with instances of one of the sub-classes. The sub-classes implement an interface with the save method. When loading a saved element, you do not know the class you are loading. Therefore I was considering having the load method in the base class, but this raised the question: how do I instantiate an element from one of the sub-classes in the base class ?
For clarity, here is some simple code:
class BaseClass:
def load(self):
#load element of subclass
return subclass_element
class myInterface:
__metaclass__ = ABCMeta
#abstractmethod
def save(self):
raise NotImplementedError
class SubClass1(BaseClass, myInterface):
def save(self):
#save the element
class SubClass2(BaseClass, myInterface):
def save(self):
#save the element
I'm also open to any suggestions in favor of a different design. I'm not sure I'm not implementing an anti-pattern.
EDIT 1: Adding a factory class
From my understanding of what #Vishal_Raja and #Gholamali-Irani suggested:
class SubClassLoader: #this is our factory class
registered_subclasses = {} #static dict of subclasses
#StaticMethod
def register(classname, class):
SubClassLoader.registered_subclasses[classname] = class
#StaticMethod
def get_instance(filepath):
classname, arguments = get_classname(filepath)
if classname in SubClassLoader.registered_subclasses:
return SubClassLoader.registered_subclasses[classname](arguments)
else:
raise TypeError("Unknown class %s" % classname)
class BaseClass:
pass
class myInterface:
__metaclass__ = ABCMeta
#abstractmethod
def save(self):
raise NotImplementedError
class SubClass1(BaseClass, myInterface):
def save(self):
#save the element
class SubClass2(BaseClass, myInterface):
def save(self):
#save the element

First of all:It is bad design to make a dependency from parent to child. Inheritance (of child from parent) is a type of dependency. If you add another dependency from parent to child, you make a circular dependency and it's very hard to maintain and extendable.
In Object Oriented Design Heuristics we have:
Heuristic 5.1: Derived classes must have knowledge of their base class by definition,
but base classes should not know anything about their derived classes.
Why?
If base classes have knowledge of their derived classes, then it is
implied that if a new derived class is added to a base class, the code
of the base class will need modification. This is an undesirable
dependency between the abstractions captured in the base and derived
classes. We will see a much better solution to these types of
dependencies when we discuss the topic of polymorphism later in this
chapter. see reference
Therefore, it is bad design to put Load() into parent.
Secondly: you said:
when loading a saved element, you do not know the class you are loading.
So, your client only depend on Save() method. Therefore, their is not dependency between your client and parent. Your client only depend on the myIntrface.
Finally: your client should define an attribute from myInterface. Then you only need another class that inject the object to your client attribute. (like Factory class -as #VishalRaja's answer- or Dependency Injector class). Then you can put all desired configuration in it to decide which class instances should be passed.

Why don't you create a separate factory class which ensures the right save implementation depending on the subclass type?

Related

Aren't class member varialbes as bad as global variable?

We all know the following code is bad because of the use of global variable:
a = 3.14
def inc():
global a
a += 1
inc()
b = a
It is so bad that in python one has to intentionally declare global to "break" the ban. But in the name of OO, how come the code below is justified:
class A:
def __init__(self):
self.a = 3.14
def inc(self):
self.a += 1
A_instance = A()
A_instance.inc()
b = A_instance.a
Within the scope of the class instance, isn't the member variable simply the same as global variable? "self" basically grant unrestricted access to all variable to any member function regardless the necessity, making it very stateful, prone to mistakes, and difficult to read (basically all the bad traits of global var)?
We also know the clean and better way is:
def inc(_a):
return _a+1
a = 3.14
b = inc(a)
So that the function inc() is at least stateless and has a predictable behavior. What's the best practice to use class and make it as stateless as possible? Or by definition, is OO always stateful and one has to go functional programming without classes at all? I also heard people say #static methods are stupid, break encapsulation, and should be avoided...
It comes down to whether you need to save state or not. If you do need to save state then it needs to be saved somewhere. Classes allow you to save state alongside the methods that operate on that state and enforce a class-local scope that is less error prone than storing state within a global scope.
As a concrete example, I recently implemented a Tree class for a forest simulation. One of the variables that is important to associate with a tree is its age. Where should the age of the tree be stored? It makes more sense to store it within the Tree class than outside of it.
If protecting the age of the tree from being manipulated by code outside of the class was important, I could have used Python's excellent #property syntax for that purpose, or less directly through the Python _varname variable naming convention.
Within the class, yes, the age of the tree is visible to the other methods, but that is a relatively narrow scope, certainly not akin to a global scope if your classes are written with a single responsibility in accord with SOLID object oriented design principles.
Now the reason why the concept of self is not considered bad practice is that if you are to create a class everything within that class ought to be related in one way or another which usually is class attributes that class instances are initialized with via the __init__ dunder method. Basically, if you are going to create a class then there ought to be a link of some sort, a class global if you will which are class attributes
usually the idea that creating classes with just self like this
class A:
def __init__(self):
self.a = 3.14
def inc(self):
self.a += 1
is not something that is often seen, rather people chose the way which is generally in many opinions considered cleaner and more predictable
class A:
def __init__(self, a):
self.a = a
def inc(self):
self.a += 1
With this when you declare class instances you have more control of what is actually there, so class instances are hence declared with variables
A_instance = A(3.14) #a will be 3.14 in this instance
B_instance = A(3.142) #a will be 3.142 in this instance
and so on.
Class variables that are declared outside the __init__ function but inside the class, itself are considerably different and that would look like
class A:
a = 22/7
def __init__(self):
....
with this a would be a global variable throughout the class(not the instance but the class itself). So what does that look like
class A:
a = 22/7
def __init__(self, item):
self.item = item
A_instance = A(3.14)
B_instance = A(5)
Although A_instance and B_instance are completely different and A_instance.item will equal 3.14 while B_instance.item will equal 5 both of these will have the class variable a as 22/7
A_instance.a #this will return a value of 22/7
B_instance.a #this will also return a value of 22/7
So the class variable remains consistent/the same throughout all instances of that class unless it is actively altered.
Point is if you are going to create a class it should have specific variables that are intertwined with each other and affect all a particular group of functions, these are the functions you make into class methods as such the use of self within classes is not wrong if used properly

Kotlin: Scoping using Object vs Class

I have a few data classes, that is short, so I group them together in a file.
I can defined them in a Kotlin file as it is, but would prefer it to be scope within a class/object, so the file is not just a file, but under class/object for better grouping
I could do
object Model {
data class Result(val query: Query)
data class Query(val searchinfo: SearchInfo)
data class SearchInfo(val totalhits: Int)
}
and I could also do
class Model {
data class Result(val query: Query)
data class Query(val searchinfo: SearchInfo)
data class SearchInfo(val totalhits: Int)
}
They both looks the same to me. What's the different, and if there's a preferred way in term of scoping my data classes?
I would advise against using classes for scoping other classes. As Todd explains in his answer, you can use sealed classes which offer an actual benefit of exhaustive when checks. If you don't need this feature, Kotlin has a built-in mechanism for scoping - packages:
package org.company.model
data class Result(val query: Query)
data class Query(val searchinfo: SearchInfo)
data class SearchInfo(val totalhits: Int)
I can defined them in a Kotlin file as it is, but would prefer it to be scope within a class/object, so the file is not just a file, but under class/object for better grouping
There's nothing wrong with a file containing multiple top-level elements. This is a useful language feature and is used in exactly this kind of situation.
Another option is to make all of your data classes a subclass of a sealed Model class. This will give you the benefit of defining them all in one place, because Kotlin enforces that for sealed classs. Also, having the type system know about all instances of type Model is helpful in when expressions as well because then it won't require you to put an else -> block.
sealed class Model
data class Result(val query: Query) : Model()
data class Query(val searchinfo: SearchInfo) : Model()
data class SearchInfo(val totalhits: Int) : Model()
And you can just use them directly:
val r = Result(Query(SearchInfo(3))
Instead of wrapping them in another class or object, where you'd have to refer to them like this:
val r = Model.Result(Model.Query(Model.SearchInfo(3)))

Odoo 8 onchange on inherited models

I have a module that implements an onchange method on res.partner. If I create a new model that inherits res.partner, the onchange is not called. Is there a way to make the onchange general, so it's also called on inherited models?
Example:
class ResPartner(models.Model):
_inherit = 'res.partner'
#api.onchange('zip')
def _valid_zip(self):
print 'Validating zip...'
class ExtendedPartner(models.Model):
_name = 'extendedpartner'
_inherits = {'res.partner': 'partner_id'}
If I change the zip code on an extendedpartner, the onchange is not called.
You use delegation inheritance in the code above. Delegation inheritance does not work on model methods. It just simply delegates lookup of fields not found in current model to the "parent" model.
I think what you want is prototype inheritence:
class ExtendedPartner(models.Model):
_name = 'extendedpartner'
_inherit = 'res.partner'
The graphic below shows three types of inheritance available in Odoo:
You currently use the first one ("classic inheritance") in ResPartner (which inherits from res.partner) and the last one (delegation inheritance) in ExtendedPartner. I think the middle one (Prototype inheritance) would be more appropriate for ExtendedPartner. It basically works in a manner very similar to standard Python inheritance.
You can read more about different types of inheritance in the documentation (which is also the source of the image above).

Does adding public method to subclass violate LSP (Liskov substitution principle)?

If I add public method to subclass and a client program calls added method, client programs can't use parent object instead of subclass.
import unittest
class BaseClass(object):
def doSomething(self):
pass
class SubClass(BaseClass):
def doStuff(self):
pass
class Client(object):
def __init__(self, obj):
self.obj = obj
def do(self):
self.obj.doStuff()
class LSPTestCase(unittest.TestCase):
def test_call_subclass_method(self):
client = Client(SubClass())
client.do()
def test_call_baseclass_method(self):
client = Client(BaseClass())
with self.assertRaises(AttributeError):
client.do()
if __name__ == '__main__':
unittest.main()
This case violates LSP?
No as long as all the methods inherrited from the parent class follow the same contract as the parent then LSP is preserved.
the whole point of LSP is to be able to pass around a subclass as the parent class without any problems. It says nothing about not being able to downcast for additional functionality.
Adding a method to a subclass does not violate LSP. However, it does violate if you invoke that method by downcasting from a parent class.
Robert C. Martin states right in the beginning of his LSP / SOLID paper that:
select a function based upon the type of an object
(...) is an example of a simple violation of the Liskov Substitution Principle.
Generally, if you end up in situations where you need to downcast or use the instanceof operator, it's better to revisit the use of inheritance in favor of other approaches like composition.

Type of user defined class objects - Python

I am not very experienced with classes or OOP,
and I'm confused with some of the results I'm getting.
I am trying to use type() on a class I have created.
class TestClass:
pass
my_class = TestClass()
print type(my_class)
The above code returns
<type: 'instance'>
Based on my understanding my_class should be initialized as a TestClass object.. right? Why isn't the output TestClass. Also, if possible, what would I need to change to get this result?
From the documentation:
Classes and instances come in two flavors: old-style (or classic) and
new-style.
Up to Python 2.1, old-style classes were the only flavour available to
the user. The concept of (old-style) class is unrelated to the concept
of type: if x is an instance of an old-style class, then x.__class__
designates the class of x, but type(x) is always <type 'instance'>.
This reflects the fact that all old-style instances, independently of
their class, are implemented with a single built-in type, called
instance.
By not inheriting from object, you create an old-style class, so type(my_class) behaves like it does.
Inherit from object and your problems will go away:
class TestClass(object):
pass
In Python 3, all classes are new-style classes, which is nice.
If you want TestClass to be an object, you have to specify it like so
class TestClass(object):
pass