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.
Related
How should I properly satisfy the Liskov Substitution Principle in this sample?
class User(ABC): # App core logic
def add_photo(self, photo: bytes, ) -> None:
...
class FacebookUser(User): # API interation logic
def add_photo(self, photo: custom_type, ) -> None:
... # Set of Facebook specific actions.
super().add_photo(photo=photo.bytes, )
I know 4 solutions:
Name mangling. Flaws:
Forcing me to rename all the existing code with
Parent.add_photo and probably all the rest methods.
Composition. Flaws:
2.1. Can't reflect the logical relation between the classes.
2.2 Forcing me to implement (proxy) methods for every Parent method.
if checking for the self object type inside the method. Flaws:
3.1. Additional complexity and clumsy branches.
Implement convert_photo method from custom_type to bytes type inside the FacebookUser child class. Flaws:
4.1 I still need to place a new convert_photo method inside some kinda "event" method (set of methods) and the best name for it is add_photo.
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
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?
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
I'm a little confused with the two terms, here's what I know:
Polymorphism is the ability of object of different types to be handled by a common interface. While duck typing, is a kind of dynamic typing that allows objects of different types to respond to the same methods.
From what I understand, polymorphism is more about creating an interface that can be shared across different classes. And duck typing is about loose typing that will allow methods to be called as long as it is found on the receiver of the message.
Is this correct? I'm pretty confused on the two, they seem related but I do not know what their relationship is. Thanks a lot in advance!
Polymorphism (in the context of object-oriented programming) means a subclass can override a method of the base class. This means a method of a class can do different things in subclasses. For example: a class Animal can have a method talk() and the subclasses Dog and Cat of Animal can let the method talk() make different sounds.
Duck typing means code will simply accept any object that has a particular method. Let's say we have the following code: animal.quack(). If the given object animal has the method we want to call then we're good (no additional type requirements needed). It does not matter whether animal is actually a Duck or a different animal which also happens to quack. That's why it is called duck typing: if it looks like a duck (e.g., it has a method called quack() then we can act as if that object is a duck).
So are these related? They are simply separate features that a programming language may have. There are programming languages which have polymorphism but that do not have duck typing (such as Java). There are also languages that have polymorphism and duck typing (such as Python).
This is an example for Polymorphism in Python.
class Animal:
def __init__(self, name): # Constructor of the class
self.name = name
def talk(self): # Abstract method, defined by convention only
raise NotImplementedError("Subclass must implement abstract method")
class Cat(Animal):
def talk(self):
return 'Meow!'
class Dog(Animal):
def talk(self):
return 'Woof! Woof!'
animals = [Cat('Missy'),
Cat('Mr. Mistoffelees'),
Dog('Lassie')]
for animal in animals:
print(animal)
print(animal.name + ': ' + animal.talk())
This is an example for duck Typing in Python.
class Duck:
def quack(self):
print("Quaaaaaack!")
def feathers(self):
print("The duck has white and gray feathers.")
def name(self):
print("ITS A DUCK NO NAME")
class Person:
def quack(self):
print("The person imitates a duck.")
def feathers(self):
print("The person takes a feather from the ground and shows it.")
def name(self):
print("John Smith")
def in_the_forest(duck):
duck.quack()
duck.feathers()
duck.name()
def game():
for element in [Duck(), Person()]:
in_the_forest(element)
game()
In polymorphism we see subclass (Cat and Dog) inheriting from the parent class (Animal) and overriding the method Talk.
In case of duck typing we don’t create a subclass instead new class is created with method having same name but different function.
Short Answer:
Duck typing is one way of achieving Polymorphism.
Another way is by using static typing.
Long Answer:
There are two different concepts involved here, typing and programming technique.
Duck typing is a type of typing. And typing means when to throw error when an object passed around isn't what is expected. Duck typing is a kind of typing where it throws error when the program is running and the method being called isn't available. Static typing comes with compile time checking, so if the type info doesn't match, it will throw error when you compile the code. And that is typing.
Polymorphism is a programming technique where you allow multiple types of object to fulfill certain responsibilities. You can do that by using a base type to represent all the child class types. You can use duck typing to represent all the different types that have the needed methods. You can use an interface to represent all the types that implement the interface.
There are answers saying polymorphism is inheritance, and that is not correct. Although you can use inheritance to create polymorphic behavior and usually that's what you do, but that's not what polymorphism is about.
For one, you don't need inheritance to have polymorphism as described above.
Secondly, the term "Polymorphism" is more meaningful in the context of the client code that depends on abstraction, and not the implementation code. Just because you have a super class and a few other classes that inherit from it and overriding some methods does not mean it's polymorphism, to create polymorphism you have to write client code in a polymorphic way to consume these classes.
Two type Polymorphism
Method overloading(Compile time Polymorphism ).
Method overriding(Run Time Polymorphism ).
Method overloading :- same function name and different data type is known as Method overloading
Example :
int addTwovalues(int a, int b)
{ return (a+b)}
float addTwovalues(float a, float b)
{ return (a+b)}
Method overriding :- same function name and same data type but different Class
is known as Method overriding.
class a
{
virtual int addtwovalues()
{ // to do }
}
class b:a
{
override int addtwovalues()
{ // to do }
}
a obj=new a();
obj.addtwovalues();
b objb=new a();
objb.addtwovalues(); //run time Polymorphism