Full Transcript

CSIT121 Object-Oriented Design and Programming Dr. Fenghui Ren School of Computing and Information Technology University of Wollongong 1 Lecture 1 outline Computer programs Programming...

CSIT121 Object-Oriented Design and Programming Dr. Fenghui Ren School of Computing and Information Technology University of Wollongong 1 Lecture 1 outline Computer programs Programming languages What object-oriented means Object-oriented analysis (OOA) Object-oriented design (OOD) Object-oriented programming (OOP) Python IDLE Your first object-oriented program in Python 2 Digital World In modern life, we are surrounded by digital electronic devices Microprocessors + Programs Digital World Automatic parking Self-driving cars Smart cruise control Military robots Home robots Automated assembly lines Computers are incredibly fast, accurate but stupid. Human beings are incredibly slow, inaccurate but brilliant. Together they are powerful beyond imagination. Albert Einstein?… Leo Cherne?... Stuart Walesh? How to let this stupid machine do something for me? Personal Computer 1) Scanner 2) CPU (Microprocessor) 640K ought to be enough for anybody 3) Memory (RAM) Bill Gates, co-founder of Microsoft Corporation, 1981 4) Expansion cards (graphics cards, etc.) 5) Power supply 6) Optical disc drive 7) Storage (Hard disk or SSD) 8) Motherboard 9) Speakers 10)Monitor 11)System software 12)Application software 13)Keyboard 14)Mouse 15)External hard disk By User:HereToHelp, CC BY 2.5 16)Printer One of the most important components is missing here ! Let a computer do something! Computers don't do anything without someone telling them what to do How to let a computer to do something? Instruct it How to instruct a computer to do something? Use a language to instruct it How to use a language to instruct a computer to do something? Write a sequence of instructions in a language – a program How to write a program? Learn programming – this subject ! How computers work The focus of CSIT121 System Software By Kristoferb, CC BY-SA 3.0 class HelloWorldApp: def greet(self): // Display "Hello world!" print("Hello object world!") greeter = HellowWorldAPP() greeter.greet() How computer programs work x86 instructions ----------------------- ADD add SUB substract MUL multiply Central CMP compare INC increment Processing MOV move data Unit … input output (CPU) program in memory Program Task: Code machine instructions z=x+y 00FF 01101001 read CPU instructions 01101010 read 00FF:F0F0 … add main ≈ 00FF:F0F1 11100101 write Read location x Read location y memory Program Add Data 10000100 x Write to location z ≈ 01001011 y … z The instruction binaries are not real and for illustration only Evolution of Programming Languages Machine Symbolic High-level languages languages languages 1950 1950 1960 10001101 mov al,40 weight = mass * 9.8; 00111100 add al,dl if(weight > MAX_WEIGHT) 00101101 cmp cl,dl status = sendWarning(); 11000101 call RESET 1989 – C 1991 – Python 1995 – Java 1998 – C++ Your first task: “Hello, World!” How do people say hello to the world? Hello G’day 你好 Bonjour ‫ﻣرﺣﺑﺎ‬ こんにちは 여보세요 How to instruct your computer to say hello to the world ? “Hello World” programs Intel x86 instruction set for 32-bit Linux Intel x86 instruction set for 16-bit DOS.model small section.data.stack 100h str: db 'Hello world!', 0Ah str_len: equ $ - str 01011001.data section.text 11100100 Assembly msg db ‘Hello world!$' global _start … _start: compiled 10100101.code mov eax, 4 start: mov ebx, 1 11000100 mov ah, 09h mov ecx, str 01101011 lea dx, msg mov edx, str_len … int 21h int 80h mov ax, 4C00h mov eax, 1 int 21h mov ebx, 0 Machine code end start int 80h Low #include Levels of programming languages int main() { compiled C printf("Hello World!"); } VM VM public class HelloWorldApp { public static void main(String[] args){ compiled System.out.println("Hello, World!"); Java } } High interpreted print "Hello World!" Python Programming languages Anything that can be done using one Compiled languages language can be done using any language. Compiled to machine code Some language may be easier for certain things Architecture-dependant, high performance Assembly, C, C++ Compiled to bytecode Architecture-neutral (running in a virtual machine) Java The differences are becoming fewer Interpreted (scripting) languages Programming languages without explicit compilation, interpreted at run-time JavaScript, PHP, Perl, shell Python is used without compilation but is compiled to bytecode on the fly and running in a virtual machine Simple and fewer lines of code, less access to computer native resources, slower execution Programming Programming is a problem-solving activity A program tells the computer how to solve a specific problem A problem can be broken down into a set of sub-problems There are many ways how a problem can be subdivided into sub-problems The subdivision affects the program implementation Programming is not very difficult, but time-consuming The most challenging part about programming is to match the subdivision of the problem with the program design methodology Computers cannot guess what problems you are solving. They simply follow your program instructions even though your instructions may be wrong A lot of time will be spent to figure out why the computer does not do what you expect it to do - debugging Remember? Brilliant Humans beings are incredibly slow and inaccurate The subject Objective Learn the Object-oriented view of problem analysis and solving Learning Outcomes 1. Effectively design and implement object-oriented programs in an integrated development environment; 2. Demonstrate an understanding and appreciation of the concepts of a well-structured solution and good coding style within an object-oriented programming environment; 3. Create correct and maintainable object-oriented programs using an object-oriented programming language; 4. Apply the principles of reuse in software design and implementation This subject is not just about Python, but you will learn OO programming in Python Learning programming Learn by doing If you want to learn programming, you must “do” programming Spend sufficient time doing it Learning stage Applying stage Lectures Labs Assignments Discuss Do it Apply what learnt with examples like examples from examples You should listen to what You must do exercises if you the lecturer says about what want to learn programming. When you are ready, you will on the presentation slides; If you do not spend sufficient find assignments not very Slides are not for you to time to actually write actual difficult to complete read - books are code, you are not learning programming. Objects Physical objects: a tangible thing that we can sense, feel, and manipulate Software objects: models (class) of something that can do certain things (behaviors) and have certain things (data) done to them A software object is a collection of data and associated behaviors. 17 Object-oriented analysis, design & programming Object-oriented means functionally directed toward modelling objects. Terms: Object-Oriented Analysis (OOA) Object-Oriented Design (OOD) Object-Oriented Programming (OOP) 18 Object-oriented analysis, design & programming What to do? Object-Oriented Analysis (OOA): looking at a problem, system or task and identifying the objects and interactions between those objects. How do it? Object-Oriented Design (OOD): converting requirements into an implementation specification. Name the objects, define the behaviors, and specify object interaction. Do it ! Object-Oriented Programming (OOP): converting the design into a working program that does exactly what the customer wants. 19 Object-oriented analysis OOA needs to consider the features of objects belonging to the same class Features of objects: names, attributes, behaviours, relationships, etc Objects are differentiated based on the values/instances of these features (Data & Functions) If objects share the same structure of features. We define the object’s structure as a class. Classes are blueprints for creating objects. They describe the general attributes and behaviours of objects. But classes do not contain Data and can’t be executed directly. Objects are the instances of classes. Objects contain data and can be executed. 20 Object-oriented analysis An object-oriented program may contain multiple objects, which are instances of multiple classes. OOA needs to consider the structure and relationships of multiple classes in a program How to describe the horizontal relationships between classes not in the same family? Association Multiplicity Aggregation Composition How to describe the hieratical relationships of classes within a class family? Single inheritance Multiple inheritances Abstract class Polymorphism How to organise these classes? OOD patterns 21 An example of potential objects A user of eBay might need to do Review his/her purchase/sell historical records Post a new advertisement Browse, compare and order items … 22 Object-oriented design Formally specify the structures and relationships of classes Unified Modeling Language (UML) Class diagram Sequence diagram UMLet (https://www.umlet.com/) The iterative design and development model will be used Initialising class design using the class diagram Evaluating the class design in scenarios/tasks using the sequence diagram Implementing the design and testing the program Updating the class design Repeat the above steps till a satisfactory evaluation results 23 Object-oriented design UML class diagram UML sequence diagram 24 Object-oriented programing Using a particular object-oriented programming language to implement the design Java C++ Python Following the language syntax and specification Compile and/or execute the program Test the program Unit test Integration test This may involve the modification of existing designs and re-evaluation. 25 Python Interpreted Targeted towards short to medium- sized projects Useful as a scripting language Java file.class file Java VM Runtime Code Compiler Computer Env Code Interpreter Computer Guido van Rossum Python file Python interpreter A Dutch programmer, the creator of Python Why Python Python works on different platforms (Windows, Mac, Linux, Raspberry Pi, etc). Python has a simple syntax similar to the English language. Python has syntax that allows developers to write programs with fewer lines than some other programming languages. Python runs on an interpreter system, meaning that code can be executed as soon as it is written. This means that prototyping can be very quick. Python can be treated in a procedural way, an object- oriented way or a functional way. Python will also be used in your 2nd and 3rd year subjects. 27 Python installation Windows Mac OSX Linux 1) Chances are you already 1) Download Python from 1) Python is already have Python installed. To python.org/downloads. installed. check run Python from 2) Run 'python’ using the 2) Open a terminal the terminal. run command. and run python or 2) If not, install Python -or- run Idle from finder. through your Run Idle from the Start distribution's package Menu. system. Python indentation Unlike in Java, in Python whitespace (think tabs and spaces) matters. Instead of using braces {} to designate code blocks, Python uses the indentation. This was done to promote readable code. In Java, you may or may not indent and it will work. In Python, you must indent. Hello.java 1 public class Hello { 2 public static void main(String[] args){ 3 System.out.println(); 4 } 5 } hello.py 1 def hello(): 2 print("Hello world”) 3 4 def does_nothing(): 5 pass 6 7 hello() Python comment While commenting is flexible it is good practice to comments.py comment code with # 1 # This is a file full of comments and code. comments before code in 2 question. 3 def hello(): 4 """ print 'Hello world' 5 this comment can be multi-line""" Comment methods with a 6 print("Hello world”) # this is in-line 7 hello() doc string (""") on the first line in a method that way it will be used in help(). Python comments.py 1 1 # This is a file full of comments and code. Python can read the 2 2 3 3 def hello(): function comments 4 """ prints 'Hello world' and make them 5 6 this comment can be multi-line""" print("Hello world”) # this is in-line available when you 7 hello() need them. >>> hello() Hello world To access these >>> help(hello) comments call Help on function hello in module __main__: help(function name). hello() prints 'Hello world' this comment can be multi-line What is IDLE? IDLE is Python’s Integrated Development and Learning Environment. It has the following features: cross-platform: works mostly the same on Windows, Unix, and macOS Python shell window (interactive interpreter) with colorizing of code input, output, and error messages multi-window text editor with multiple undo, Python colorizing, smart indent, call tips, auto completion, and other features search within any window, replace within editor windows, and search through multiple files (grep) debugger with persistent breakpoints, stepping, and viewing of global and local namespaces configuration, browsers, and other dialogs IDLE documentation: https://docs.python.org/3/library/idle.html Python IDE – IDLE https://www.python.org 33 Suggested reading Python 3 Object-Oriented Programming Preface Chapter 1: Object-Oriented Design Python https://www.python.org/ https://www.w3schools.com/python/ CSIT121 Object-Oriented Design and Programming Dr. Fenghui Ren School of Computing and Information Technology University of Wollongong 1 Lecture 2 outline Object-oriented concept Class design Encapsulation Basic Unified Modelling Language (UML) Class design with the UML class diagram 2 Focus of this subject This subject is not only about Python If know a programming language and you know how to use computers, it does not mean that you can develop software systems If you know alphabet and you can type quickly, this may not be enough to write a novel To become a programmer - you need to be familiar with advanced software development concepts - you need to know how to efficiently utilize these concepts using appropriate programming languages Software development challenge Software development has unique challenges which are not common for other industries When you design a car you can foresee how it will look like when it is made Reverse engineering can reproduce car design documents (identical to the original ones) However… When a program is executed, it How to design is a sequence of invisible electrical programs signals which represent binary when you can't microprocessor instructions see the final It is practically impossible to product? reproduce the original program code from binary instructions Imperative Programming Concept The oldest concept where a program consists of a sequence of commands for the microprocessor to execute Example: Assembly language is a symbolic representation of microprocessor instructions with a one-to-one mapping pushl %ebp 11010011 movl %esp, %ebp 01010010 addl 8(%ebp), %eax 10000011 How to increase productivity of software development? When you virtually have to 'live in the microprocessor' and think like a machine to write even a simple program, you cannot be productive It is close to impossible to reuse assembly code. You need to start every new project practically from scratch How to find an efficient design methodology ? We could try to borrow ideas from other industries Can software be built from pre-designed pre-tested parts too? Cars are made of preassembled parts To build a new car you don't need to design every part from scratch – some parts can be reused from previous models, or be purchased from new suppliers without making any changes to their internal structure How to find an efficient design methodology ? We could try to borrow ideas from other industries Can software modules be designed with clearly defined interface to simplify their integration? To assemble a home theatre you can buy modules from different manufacturers according to your needs They can be easily plugged together as their interfaces are standardized How to find an efficient design methodology ? Other examples: From transistors to integrated circuits From bricks to pre-fabricated panels Transition to pre-fabricated generic reusable modules with well-defined interface components has been a common trend for all industries To increase productivity, computer programming had to follow the same trend Research on efficient programming concepts led to the development of the Object-Oriented Design methodology in the late 60th Objects Object Oriented Design methodology introduces the concept of objects Like mechanical and electrical parts in other industries, objects become major software building blocks Rather than think about commands and microprocessor instructions, you need to think about objects, their properties, their behaviors and how their interactions can implement your program functionality In general, objects can receive messages from other objects and respond. To use them, you don’t need to worry about their internal structure. It is hidden. Message Object Result Evolution of OOD languages The OOD methodology has substantially evolved since it was introduced in the 60th Evolution of OOD programming languages reflects the evolution of OOD programming concepts 1967 1980 1983 1991 2000 Simula Smalltalk C++ Python C# Created a basis Significant Implemented Supports OOD Originated from for all following revision of latest concepts concepts with Java, however OO languages. Simula. of OOD. Very the focus on deviated It had some Development efficient Internet and substantially shortcomings environment compiler. platform over years. related to with tools Standardised by independent Works on MS debugging and commonly used ISO. applications..NET platform. support of now: debugger, Standardised by multiple code editor, ISO. hardware class library platforms Object Based Design The main purpose of any program is to process data The major task of OOD is how to split the system's data and behaviour into a set of interacting objects A functional view of the program An OOD view of the program Main Data processing object methods Object2 Object1 Data to be processed Object4 Object3 What can an object do ? When you describe your program as a collection of interacting objects, you need to have a clear idea what role the objects will play in your application An object may play just one role, or several typical roles Role Stereotypes Collect, store and Provide services provide data and computing (data provider) (service provider) An object Generate other Make decisions objects and maintain (controller) relationship between them (constructor) Analyse events and delegate tasks to others (coordinator) Internal structure of objects Each object implements a certain part of the system functionality. Thus, it should contain data and methods to process this set of data Object Data How can objects interact? Data processing methods Object To interact with other objects, they Data also include interface methods Interaction between objects is Interface Data possible only through interface methods processing methods methods What does an object look like? Physically, it consists of binary data and microprocessor instructions, which occupy a reserved block of memory ( its actual layout is system-dependent) Links between objects can be established at the compilation time or dynamically at run time Logically, it must be declared in your program by classes When an object is declared, it is given a unique name Looking through a program code, you can see all objects declared there and follow the logical relationship between them How can objects be created ? Parts of mechanical systems are made based Objects of a software system are generated based upon their description – blueprints upon their description – classes Instantiation circle1 circle2 circle3 A class is an abstraction defined by a programmer but NOT placed in the computer memory An object is an instance generated and placed in computer memory (many similar objects can be generated from one class) Classes Classes can be interpreted as blueprints, or prototypes for objects You can’t use classes directly, you only can create objects based on their classes. Objects are not necessarily clones even when they are created from the same class For example: a class Polygon can be used to create triangles and rectangles as instances (objects) To generate different objects, we may specify different properties such as the number of sides, the lengths of those sides, their colors The object behaviour is things that require actions - how the circumference is calculated, how the object is displayed, etc Classes Conceptual class (start): OOA From your mind A rough description of items and concepts Can only understood by yourself Readable class (through): OOD A formal description of classes Data structure, functions, relationships Can be understood by anyone with the background knowledge UML Class Diagram Executable class (target): OOP Programs Can be used by everyone Create objects Summary: Class vs. Object A class is a template for objects, and it is a logical entity. A class defines properties and functions, such as data type, structure, range, requirements and behaviors of methods. A class does not contain the actual values and just acts as a container. By considering the difference between the actual values of a class, one class can have multiple different objects. A class is declared only once, and no memory is allocated for a class. Therefore, a class can not be executed. Summary: Class vs. Object An object is an instance of a class, and it is a physical entity. An object has a state in which all of its properties MUST have values. Objects can be created many times, and each object will be allocated memory once created. Objects created from the same class will have different locations in the computer memory. Objects are executable. However, the objects of the same class may act very differently. Object features 1. Identity – Correct interaction between objects may not be possible without reliable identification of objects – Each object has a unique identifier that is used to recognize it class Polygon:..... Instantiation of objects presumes that all objects will be given unique identifiers ID: triangle1 ID: squareA ID: triangle2 ID: rhombus1 Identity (a unique name) of an object can be: specified by a programmer assigned by another object that takes a role of constructer Object intrinsic features 2. State Object-Oriented concept presumes that objects store data all data are stored with the purpose of reflecting properties (or attributes) of objects Example properties of a circle: (x,y) coordinates of the centre, r radius properties of a bill: due date, amount to pay A set of actual values stored in an object is referred as an object state ID: Circle1 ID: Circle2 Some attributes Object x: 25.0 x: 0.0 cannot be properties y: 10.2 Object state y: 0.0 changed. (or attributes) r: 7.5 r: 5.5 They are called pi: 3.141 pi: 3.141 constants Objects instantiated from the same class will have – different IDs, – the same attributes, – the same or different states Object intrinsic features 3. Behaviour Instantiated objects are expected to act and react according to their roles ( collect and store data, make decisions, provide services, etc ) A set of supported actions defines object behaviour (what it does) Actions in OOD are called methods ID: Circle1 x: 3.0 Some methods can change the object y: 1.0 state (changeRadius, …). r: 7.5 These methods are called mutators changeRadius() Methods Determine Some other methods can only access the changeCoordinate() value of an attribute without changing the what the getMyRadius() object does object state (getMyRadius, …) getMyCoordinates() These methods are called accessors. calculateArea() Fundamental OOD concepts Encapsulation Some industrial products are sealed to prevent access to their internal components. They can be used only through external terminals OOD stipulates that to prevent unauthorized access to the most critical object attributes and methods, they need to be placed into a protective wrapper inside the object to make sure that: - well designed and tested objects cannot be alternated or corrupted by other poorly designed objects - hidden components can be modified without affecting object interaction ( providing that interface methods are not affected by modifications) Attributes and Methods which are specified as Private are hidden inside Private objects and cannot be accessed Attributes directly from outside Public methods Private Methods specified as Public can be Methods used for interaction with other objects Fundamental OOD concepts Encapsulation According to OOD, interaction between objects can take place only through public methods In general, all attributes should be specified as private. If they need to be accessed from outside, this should be possible only through a limited set of public methods ( Accessors or Mutators ) Methods which are irrelevant to object interaction also should be private If a private attribute, or a private method can be accessed directly from outside, this indicates a serious design oversight (a safety bug) Bank account Internet Banking money getBalance() User interface transaction() payBill() Account transfer() management methods Quiz You need to implement an object Clock that - counts time - provides the current time on request - can change on request the output format from 24hrs to AM/PM - can set alarm - can make beeping sound when alarm is on ID: Clock1 1. Which methods should be hours: 12 public and which ones should be minutes: 25 private ? seconds: 34 + acc getTime() 2. Which methods are accessors + mut setOutputFormat() and which ones are mutators? + mut setAlarm() - acc countTime() - acc makeSound() Verbal description, ambiguity, confusion,… You may try to describe your program using a natural language Natural languages do not have exact rules for technical descriptions Even a simple natural language description can be interpreted differently by different listeners (the more details you provide, the higher the chance for misinterpretation) A formal modelling language is needed to describe software designs unambiguously UML is a formal tool for software systems modelling What is UML and how can it help? UML (Unified Modelling Language) is a consolidation of research on OO modelling UML was accepted by the ISO as an international standard in 2000 UML can be used 1. To make sketches when you want to communicate key points of your program architecture 2. To provide a formal and detailed specification of a software system 3. To generate code directly from UML diagrams if a special tool is used UML models cannot be misinterpreted UML is scalable and can be used for small and big projects UML facilitates the software development process and simplifies debugging UML Class Diagrams Class diagrams: – Contain classes and relations between them – Specify class attributes sufficient to describe any state of the object instantiated from a class – Specify methods sufficient to implement a required object behaviour – Specify object state UML class symbol The most basic class symbol is a box with the class name. It is used when class properties are not important (usually at initial stages of system design) Adding in more details may be needed at later stages Attributes, or data types Methods class name Person lastName: String attributes age: int height: int getName(): String The level of details depends on setName(): Void who the diagram is intended for methods Class symbols are the building getHeight(): String blocks of class diagrams getAge(): String UML class symbol Role stereotypes Visibility prefixes > Role stereotype Person Class name - name:String Prefix attributeName: Data type - age:int Data type Prefix methodName(): Return data - height:int type - rate:int {read only} + getName():String Prefixes: + setName():void + : public attributes and methods + getHeight():int - : private attributes and methods + getAge():int # : protected attributes and methods + setAge():void {read only}: constant + main():void static ___ (underline): static (class) attributes and methods UML object symbol > A class Person - name:String - age:int instantiation object name class name underline Jack : Person Specific values for name = "Jack Smith" each attribute age = 21 ( object state ) A simplified UML representation Jack : Person when state is not important Class Relationship Class symbols by themselves provide very limited information about your program architecture. A model of the system should reflect the relationship between classes OOD defines the following types of relationships between classes: - association - aggregation - composition Association Indicates that one class uses another class Association can be described as “has” or “uses” type of relationship uses Lecturer Projector has Country Capital City 1 Name: name: has User Bank Account 0..* Aggregation A class can have references to objects of other classes as members. This is called aggregation and is sometimes referred to as a has-a relationship. The objects are fields of the class. Example: An AlarmClock object needs to know the current time and the time when it’s supposed to sound its alarm, so it’s reasonable to include two references to Time objects in an AlarmClock object. Composition Composition is a special kind of association Composition reflects “contains” or “owns” type of relationship Components “live” inside the container with their lifespan synchronized with the container Deletion of the container destroys the component objects Cube Vertex 8 PC 1..2 1..2 1 1 Processor Monitor Keyboard Mouse Quiz What is the most appropriate relationship between the following classes: Table Desktop Legs Table 1 3..4 Desktop Leg Defining classes The problem of defining an appropriate collection of classes and their relationship for your project is generally non-trivial Although there are some complicated theories that should help, practically you can mostly rely on your experience and intuition We are going to look at a made-up simple application scenario to show how to determine the classes and properties that seem appropriate What makes a class model good ? Two main objectives when constructing the class model: 1. build a system, quickly and cheaply, that satisfies users’ needs 2. build a system that will be easy to maintain in the future How are these objectives achieved? 1. “every piece of system behavior must be provided in a sensible way by the objects of the classes we choose” 2. “a good class model consists of classes which represent enduring classes of domain objects which don’t depend on the particular functionality required today” To do this, we... need some number of design iterations to develop a good class model focus on the domain classes first rather than classes arising out of implementation considerations Identifying Classes We use key domain abstractions Domain: application area we are working with, e.g. Library Classes are the principal abstraction of interest at this point How to identify the right classes? Noun Identification Technique This involves taking a coherent, concise statement of the requirements of the system and underlining its nouns and noun phrases; that is, identifying the words and phrases that denote things. This gives a list of candidate classes, which we can then whittle down and modify to get an initial class list for the system. Identifying Classes Noun Identification Technique Nouns and noun phrases denote things and lead to candidate classes. We discard: library (outside the scope) short-term loan (an event) member of the library (redundant, same as library member) week (time, not a thing) item (too vague) time (outside scope) system (meta-language, not part of the domain) rule (meta-language, not part of the domain) Noun Identification Technique First-cut list of possible classes: book journal copy ( of book) library member member of staff Relations between Classes We can see that a copy is a copy of a book a library member borrows/returns a copy a member of staff borrows/returns a copy a member of staff borrows/returns a journal. We record the information pictorially in the UML class model. Associations noun class verb association An instance of an association is called a link in UML. A simple association is represented by a solid line between two classes is a copy of Copy Book A simple association between classes When are classes (A and B) associated? An object of class A sends a message to an object of class B; An object of class A creates an object of class B; An object of class A has an attribute whose values are objects of class B or collections of An object of class A receives a message with an object of class B as an argument. A good class model... does not distort the conceptual reality of the domain but... it also permits a sensible implementation of the required functionality Multiplicities We had showed a “1” at the Book end of the association “is a copy of” because every copy is associated with just one book. Maybe any number of copies of a given book is needed, therefore, the multiplicity must be considered. An exact number – simple by writing it: 1 or 2,4,6,8 A range of numbers – using two dots between a pair of numbers: 1..10 An arbitrary, unspecified number - using * or n Relations between Classes Multiplicities 1: Each (each copy is a copy of just one book) 1..*: Maybe one or many (there may be on or many copies of a given book) 0..1: Maybe zero or one (a copy can not be borrowed by more than one person 0..*: Maybe zero or many (a person can borrow none or many copies of books) Operations and Attributes We had identified Classes Their relationships (association) However, the system still cannot be proceeded without considering The state of objects of these classes The behaviour of objects of these classes We need further to identify Attributes Methods Attributes The attributes of a class describe the data contained within an object of a class, they have: 1. Name 2. Type (either primitive types, integer, string etc, or classes not in the class diagram. If the type of an attribute is a class in the class diagram, it is better to record an association between the two classes) Note - check that enough data and behavior has been included to satisfy the requirements - need to consider how objects will work (collaborate) together Methods Important for a class as it defines ways in which an object processes data by itself an object interacts with others A message received is a request to perform some methods, that is, execute some methods within a class Book A method signature identifies: prefix - title: String name formal parameters (arguments, name & type) copiesOnShelf(): Int return value type borrow(c:Copy): Boolean UML Design Tools UMLet – Free UML Tool (online, download or Eclipse plugin) Downloadable version: https://www.umlet.com/changes.htm Online version: http://www.umlet.com/umletino/umletino.html Suggested reading Python 3 Object-Oriented Programming Preface Chapter 1: Object-Oriented Design Python https://www.python.org/ UMLet https://www.umlet.com/ UML diagram https://www.softwaretestinghelp.com/uml-diagram-tutorial/ CSIT121 Object-Oriented Design and Programming Dr. Fenghui Ren School of Computing and Information Technology University of Wollongong 1 Lecture 3 outline Python class and object Class implementation with Python Add attributes and methods Initialisation of objects Class vs instance variables Class vs instance vs static methods Public, protected and private variables and methods A case study 2 HelloWorld (OOD) Let's analyze the simplest possible Python OO program that has only one class and one method Class definition Class declaration class HelloWorld: pass Class body To define a class you need to: 1. Use the class keyword (spelled with all lowercase letters) 2. Specify its name. A class name is its identifier. By convention, class names - can include only letters, digits, and underscores. No spaces. - begin with a capital letter. If several words are combined, each shall start with a capital letter too - should be meaningful DpGh, Abc, R1,WelcomeToPython, StaffMember, StreamBuffer 3. The class definition line is followed by the class contents, indented. pass can be used for skipping the class body. 4. Python uses a four-space indentation to delimit the classes, rather than brackets Class definition Although our first class does nothing, we still can run the program. 1. Save the class definition in a file named HelloWorld.py 2. Implement and run the program in IDLE. Adding attributes Objects should contain data which are defined as the attribute We can set arbitrary attributes on an instantiated object using ‘.’ (dot notation). Syntax:. = Adding behaviors We have data, and it is time to add behaviors. We start with a method called ‘greet’ which prints “Hello object world”. ‘greet’ method does not require any parameters. We call the method through the dot notation:. Adding behaviors In Python, a method is defined with the def keyword, followed by a space, the name of the method, and a set of parentheses containing the parameter list. Method definition is terminated with a colon (:) The method body starts from the next line and is indented. Syntax: < methodName> ‘self’ argument With the same class definition, we can create different objects. Therefore, we need to know which object calls the methods (object methods). Object methods shall contain an argument referring to the object itself. Normally, this argument is named ‘self’. The ‘self’ argument is a reference to the object that the method is being invoked on. Of course, you can also call it by another name, such as ‘this’ or ‘bob’. But we never seen a real Python programmer use any other name for this variable A normal function or a class method does not have this ‘self’ argument. ‘self’ argument In Python OOP, a method is a function attached to a class. The ‘self’ parameter is a specific instance of that class. If you call the method with two different instances (objects), you are calling the same method twice but passing two different objects as the ‘self’ parameter When we call., we do not have to pass the ‘self’ argument into it. It is because Python automatically pass it, i.e., method(object) Alternatively, we can invoke the function on the class, and explicitly passing our object as the ‘self’ argument. ‘self’ argument More arguments A method can contain multiple arguments Use the dot notation to call the method with all argument values (still no need to include the ‘self’ argument) inside the parentheses Initialisation of objects What if we forget to call the reset() function? Initialisation of objects If we try to access an attribute without a value, we will receive an error. How do we force users to call ‘reset()’ method every time? The better way is to call ‘reset()’ automatically for every new object In OOD, a constructor refers to a special method that creates and initialises the object automatically when it is created The Python initialisation method is the same as any other method but with a special name, __init__ (the leading and trailing are double underscores) Initialisation of objects Explain your class It is important to write API documentation to summarize what each object and method does The best way to do it is to write it right into your code through the docstrings Docstrings are simply Python strings enclosed with apostrophes (') or quotation marks (") characters. If docstrings are quite long and span multiple lines (the style guide suggests that the line length should not exceed 80 characters), it can be formatted as multi-line strings, enclosed in matching triple apostrophe (''') or triple quote (""") characters. A docstring should clearly and concisely summarize the purpose of the class or method it is describing. It should explain any parameters whose usage is not immediately obvious and is also a good place to include short examples of how to use the API. Any caveats or problems an unsuspecting user of the API should be aware of should also be noted. Explain your class Instance (object) and class (static) variables Instance variables are for data unique to each instance. Instance variables are defined inside methods with the prefix ‘self’ Access via. Class (static) variables are for data shared by all instances of the class. Class (static) variables are defined outside methods Access via cls. or. Instance (object) and class (static) variables start_point_x and start_point_y are class variables Changing the class variable values with Object point1, then we can see the class variable values are modified with Object point2 However, point2 is not initialised by the new start_point (1,1). Can you guess why? Can we use Point.start_point_x and Point_start_point_y in the init() method? Class (static) and instance variables No, we can not. It is because Point is not created yet in the init() method How to resolve this problem? We use a sentinel default value instead. Sentinel Default Value Class method Problem: we still have to create a Point object first, and then we can modify the start point. Question: can we modify the start point directly without creating a Point object? Answer: yes, we can. We can define a ‘change_start_point()’ method as a class method by marking this method with a ‘@classmethod’ decorator. Then we can call the method with the class name or the object name, i.e.. or.. They do the same job but you don’t have to create an object in the first way. Class and instance method The instance method has access to the object via the ’self’ argument. When the method is called, Python replaces the ’self’ argument with the instance object. Calling class method doesn’t have access to the object, but only to the class. Python automatically passes the class as the first argument to the function when we call the class method. Summary: Python calls the instance method by passing the object instance as the first argument, and calls the class method by passing the class as the first argument Static method Question: Java has the static method, does Python also have the static method? Answer: Yes, Python also has the static method, but it is different from Java’s static method Java’s static method is the same as Python’s class method Python’s static method is the same as Python’s normal method, i.e., no object instance or class will be pasted as the first argument. Python’s static method can be defined by marking this method with a ‘@staticmethod’ decorator. You are allowed to call a static method via either., or. Static method Python access control Most OOP languages have a concept of access control. (+) public members are accessible from outside the class. (-) private members are accessible from inside the class only. (#) protected members are accessible from inside the class or sub-classes However, Python does not do this!!! Python does not believe in enforcing laws that might someday get in your way. Technically, all members are publicly available. In Python, prefixes are used to interpret the access control of members. _ (single underscore) prefixed to a member makes it protected but still can be accessed. __ (double underscore) prefixed to a member makes it private. It gives a strong suggestion not to touch it from outside the class. Any attempt to do so will result in an AttributeError. Actually, Python performs name mangling of private variables. Every private member with a double underscore can be accessed by adding the prefix ‘_’. So, it can still be accessed from outside the class, but the practice should be refrained. Python access control Python execution control A program written in C or Java needs the main() function to indicate the starting point of execution. Python does not need the main() function as it is an interpreter-based language. The execution of the Python program file starts from the first statement. Python uses a special variable called ‘__name__’ (string) to maintain the scope of the code being executed. The top-level scope (top-level code executes here) is referred by the value ‘__main__’ You can check the scope in Python shell by typing ‘__name__’ in IDEL. Python execution control When you execute functions and modules in the interpreter shell directly, they will be executed in the top-level scope ‘__main__’ We can also save a Python program as a Python file, which may contain multiple functions and statements, such as Python execution control We can use the command prompt/terminal to execute the Python file as a script We can also use the Python file as a module in another file or in interactive shell by importing it. Python execution control The import statement starts executing from the first statement till the last statement. What if we just want to use the ‘add()’ method but not print the __name__? We can use the special variable ‘__name__’ to check the scope and execute the other statements only when it executes from the command prompt/terminal but not when imported it. Python execution control However, when we execute it from the command prompt/terminal, it still executes all statements because of it being executed in the top-level scope ‘__main__’. Thus, value of the ‘__name__’ allows the Python interpreter to determine whether a module is intended to be an executable script. A case study Design and implement a Python program with OOD & OOP to calculate the length of a given line segment. Step 1: OOA To calculate the length of a given line segment, the LineSegment class can be defined. The LineSegment class should contain two points, i.e., the start point and the ending point. The length of the line segment is the Cartesian distance between the two points. So the LineSegment class should have two points (attribute) and can calculate the Cartesian distance of two points (behavior) To represent a point, the Point class can be defined. The Point class should contain the coordinate (x, y) as its attributes. A case study Design and implement a Python program with OOD & OOP to calculate the length of a given line segment. Step 2: OOD (UML) A case study Design and implement a Python program with OOD & OOP to calculate the length of a given line segment. Step 3: OOP (Python) Step 4: use the ‘__name__’ variable to ensure your testing cases are only executed in the command prompt/terminal. A further question: can you modify this design and code to calculate the total length of consecutive line segments, such as (0,0)->(3,4)->(5,7)->(2,8)? Suggested reading Python 3 Object-Oriented Programming Preface Chapter 2: Objects in Python Python https://www.python.org/ CSIT121 Object-Oriented Design and Programming Dr. Fenghui Ren School of Computing and Information Technology University of Wollongong 1 Lecture 4 outline Modules and packages Third-party libraries Test-driven development Unittest module Code coverage 2 Modules For small programs, we can put all our classes into one file and add a little script at the end to start them interacting. For large programs, it can become difficult to find the one class that needs to be edited among the many classes we’ve defined. We need to use modules. Modules are simply Python files. One Python file equals one module. If we have multiple modules with different class definitions, we can load classes from one module to reuse them in the other modules. E.g. put all classes and functions related to the database access into the module ‘database.py’. Modules The ‘import’ statement is used for importing modules or specific classes or functions from modules. E.g. we used the import statement to get Python’s built-in math module and use its sqrt function in the distance calculation Suppose we have: A module called ‘database.py’ which contains a Database class A second module called ‘products.py’ which responsible for product- related queries. ‘products.py’ needs to instantiate the Database class from ‘database.py’ module so that it can execute queries on the product table in the database. We need import Database class in the products module. We can import modules, classes or functions with different syntax Modules To import the whole database module into the products namespace so any class or function in the database module can be accessed using the ‘database.’ notation. Import database db = database.Database() # Do queries on db Modules To import just one class (Database class) from the database module into the products namespace so all the class functions can be accessed directly. from database import Database db = Database() # Do queries on db Modules If the products module already has a class called Database, and we don’t want the two names to be confused, we can rename the imported class when used inside the products module from database import Database as DB db_product = Database() Db_database = DB() # Do queries on db Modules We can also import multiple classes in one statement. If our database module also contains a Query class, we can import both classes as follows. from database import Database, Query db = Database() query = Query() # Do queries on db via query Modules Don’t do this from database import * Because, You will never know when classes will be used Not easy to check the class details (using help()) and maintain your program Unexpected classes and functions will be imported. For example, it will also import any classes or modules that were themselves imported into that file. Modules For fun, try typing ‘import this’ in your interactive interpreter. You will get a poem about Python philosophy. ☺ Package As a project grows into a collection of more and more modules, it is better to add another level of abstract. As modules equal files, one straightforward solution is to organise files with folders (called packages). A package is a collection of modules in a folder. The name of the package is the name of the folder. We need to tell Python that a folder is a package to distinguish it from other folders in the directory. We need to place a special file in the package folder named ‘__init__.py’. If we forget this file, we won’t be able to import modules from that folder. Package Put our modules inside an ecommerce directory in our working folder (parent_directory) The working folder also contains a main.py module to start the program. We can add another payment directory inside the ecommerce directory for various payment options. The folder hierarchy will look like this. Package In Python 3, there are two ways of importing modules from a package: absolute imports and relative imports. Absolut imports specify the complete path to the module in the package, functions, or classes we want to import Relative imports find a class, function, or module as it is positioned relative to the current module in the package. Package Absolute imports If we need access to the Product class inside the products module, we could use any of these syntaxes to perform an absolute import. Package Absolute imports Which way is better? It depends. The first way is normally used if you have some kind of name conflict from multiple modules. You have to specify the whole path before the function calls. If you only need to import one or two classes, you can use the second way. Easy to call functions. If there are dozens of classes and functions inside the module that you want to use, you can import the module using the third way. Package Relative imports If we are working in the products module and we want to import the Database class from the database module next to it, we could use a relative import. from.database import Database The period ‘.’ in front of the database says ‘using the database module inside the current package’. The current package refers to the package containing the module (products.py) we are currently working in, i.e., the ecommerce package. Package Relative imports If we were editing the square.py module inside the payments package, we want to use the database package inside the parent package. from..database import Database We use more periods to go further up the hierarchy. If we had an ecommerce.contact package containing an email module and wanted to import the send_mail function. from..contact.email import send_mail Inside a module We specify variables, classes or functions inside modules. They can be a handy way to shore the global state without namespace conflicts. For example, it might make more sense to have only one database object globally available from the database module. The database module might look like this: Inside a module Then we can use any of the import methods we’ve discussed to access the database object, such as In some situations, it may be better to create objects until it is actually needed to avoid unnecessary delay in the program. Inside a module All module-level code is executed immediately at the time it is imported. However, the internal code of functions will not be executed until the function is called. To simplify the process, we should always put our start-up code in a function (conventionally called ‘main’) and only execute that function when we know we are running the module as a script, but not when our code is being imported from a different script. We can do this by guarding the call to ‘main’ inside a conditional statement. Inside a module Important note: Make it a policy to wrap all your scripts in an ‘if __name__ == “__main__”:’ your_testing_code’ pattern in case you write a function that you may want to be imported by other code at some point in the future. Third-party libraries You can find third-party libraries on the Python Package Index (PyPI) at http://pypi.python.org/. Then you can install the libraries with a tool called ‘pip’ However, ‘pip’ is not pre-installed in Python, please follow the instructions to download and install ‘pip’: http://pip.readthedocs.org/ For Python 3.4 and higher, you can use a built-in tool called ‘ensurepip’ by installing it with the command ‘$python3 –m ensurepip’ Then, you can install libraries via the command ‘$pip install ’ Then the third-party library will be installed directly into your system Python directory. Third-party libraries We will learn Matplotlib (a low-level graph plotting library) in this subject. Program Testing Why test? To ensure that the code is working the way the developer thinks it should To ensure that the code continues working when we make changes To ensure that the developer understood the requirements To ensure that the code we are writing has a maintainable interface Test-driven development methdology Principle Write tests for a segment of code first Test your code (it will fail because you don’t write the code yet) Write your code and ensure the test passes Write another test for the next segment of your code Write your code and ensure the test passes … It is fun. You build a puzzle for yourself first, then you solve it! Test-driven development methodology The test-driven development methodology ensures that tests really get written; forces us to consider exactly how the code will be used. It tells us what methods objects need to have and how attributes will be accessed; helps us break up the initial problem into smaller, testable problems, and then to recombine the tested solutions into larger, also tested, solutions; helps us to discover anomalies in the design that force us to consider new aspects of the software; will not leave the testing job to the program users. Unit Test Same as Java, Python also has a built-in test library called ‘unittest’ ‘unittest’ provides several tools for creating and running unit tests. The most important one is the ‘TestCase’ class. ‘TestCase’ class provides a set of methods that allow us to compare values, set up tests, and clean up when the tests have finished. Unit Test Create a subclass of TestCase (we will introduce the inheritance next lecture) and write individual methods to do the actual testing. These method names must all start with the prefix ‘test’. TestCase class will automatically run all the test methods and report the test results Unit Test Pass the test Unit Test fail the test Unit Test more tests Unit Test Assert methods Reducing boilerplate and cleaning up No need to write the same setup code for each test method if the test cases are the same. We can use the ‘setUp()’ method on the TestCase class to perform initialisation for test methods. Organise your test classes We should divide our test classes into modules and packages (keep them organized) Python’s discover module (‘python3 –m unittest’) can find any TestCase objects in modules if your tests module starts with the keyword ‘test’. Most Python programmers also choose to put their tests in a separate package (usually named ‘tests/’ alongside their source directory). Ignoring broken tests Sometimes, a test is known to fail, but we don’t want to report the failure. Python provides a few decorators to mark tests that are expected to fail or to be skipped under known conditions. ‘@expectedFailure’, ‘@skip(reason)’, ‘@skipIf(condition, reason)’, ‘@skipUnless(condition, reason)’ Ignoring broken tests Tests results: The first test fails and is reported as an expected failure with the mark ‘x’ The second test is never run and marked as ‘s’ The third and four tests may or may not be run depending on the current Python version and operation system. Ignoring broken tests How much testing is enough? How can we tell how well our code is tested? This is a hard question, and we actually do not know whether our code is tested properly and throughout. How do we know how much of our code is being tested and how much is broken? This is an easy question, and we can use the code coverage tool to check. We can check the number of lines that are in the program and get an estimation of what percentage of the code was tested or covered. How much testing is enough? In Python, the most popular tool for testing code coverage is called ‘coverage.py’ It can be installed using the ‘pip3 install coverage’ command coverage.py works in three phases: Execution: Coverage.py runs your code, and monitors it to see what lines were executed. (command ‘coverage run ’) Analysis: Coverage.py examines your code to determine what lines could have run. Reporting: Coverage.py combines the results of execution and analysis to produce a coverage number and an indication of missing execution. (command ‘coverage report’ or ‘coverage html’) How much testing is enough? Execution: ‘coverage run -m ’ How much testing is enough? Analysis & Reporting: command ‘coverage report’ and ‘coverage html’ How much testing is enough? HTML reports Suggested reading Python 3 Object-Oriented Programming Preface Chapter 2: Objects in Python Chapter 12: Testing object-oriented programs Python https://www.python.org/ https://docs.python.org/3/library/unittest.html# CSIT121 Object-Oriented Design and Programming Dr. Fenghui Ren School of Computing and Information Technology University of Wollongong 1 Lecture 5 outline Inheritance Inheriting from Python built-in types Overriding and super Multiple inheritance issues Polymorphism Duck typing Abstract base class A case study 2 What is inheritance? Inheritance is the ability to ‘inherit’ features or attributes from already written classes into newer classes. These features and attributes are defined data structures and the functions we can perform with them. It promotes code reusability, which is considered one of the best industrial coding practices as it makes the codebase modular In Python inheritance, new classes inherit from older classes. The new classes copy all the older classes’ functions and attributes without rewriting the syntax in the new classes. These new classes are called derived/sub/child classes, and old ones are called base/super/parent classes. What is inheritance? A superclass (parent class) is a class that is being inherited. A subclass (child class) is a class that inherits from a superclass. The child object can access the base_attributes and base_methods in the parent class. The parent object can NOT access the extra_attributes, extra_methods and override_methods in the child class. The sibling object can NOT access the difference_attributes, different_methods and override_methods in another child class. Using the generalisation in UML class diagram The generalization (an empty triangle arrow) is used in the UML class diagram to show the inheritance Types of inheritance in Python Single inheritance Hierarchical inheritance Multi-level inheritance Multiple inheritance Hybrid inheritance Single inheritance Single inheritance is the simplest form of inheritance where a single child class is derived from a single parent class. Single inheritance Hierarchical inheritance Hierarchical Inheritance means there are multiple derived child class from a single parent class. Hierarchical inheritance Multi-level inheritance In multi-level inheritance, we go beyond just a parent-child relation. We introduce grandchildren, great-grandchildren, grandparents, great-grandparents, etc. We can have multiple levels where the parent class itself is derived from another class. Multi-level inheritance Question: Can the grandparent object call the child class method? Multiple inheritance In multiple inheritance, a single child class is inherited from two or more parent classes. It means the child class has access to all the parent classes’ methods and attributes. Multiple inheritance Questions: 1) Can the father object call the method in the mother class? 2) Can the mother object call the method in the child class? The multiple inheritance may have some potential issues in real-world applications, and it is not highly recommended for OOP. For example, Java does not support the multiple inheritance. Hybrid inheritance Hybrid inheritance is the mixture of two or more different types of inheritance. Hybrid Inheritance Questions: Can the father object call the grandfather class method? Can the mother object call the grandfather class method? Can the grandparent/father/mother object call the child class method? A family tree Can you design and implement Python classes for this family tree? The super class ‘object’ Technically, every class we created in Python uses inheritance. Every class will automatically inherit from the ‘object’ class if it does not explicitly inherit from a different class The ‘object’ class provides very little in terms of data and behaviors, but it allows Python to treat all objects in the same way as the instances of the ‘object’ class. The super class ‘object’ The ‘object’ class has some pre- defined methods. The ‘isinstance()’ method checks if an object is derived from a class. Return ‘true’ for yes and ‘false’ for no. The ‘issubclass()’ method checks if a class is derived from a class. Return ‘true’ for yes and ‘false’ for no. Create subclass object with superclass The 'Contact’ class is responsible for maintaining a list of all contacts. Each contact contains the name and the email address. The ‘Supplier’ class is a subclass of the ‘Contact’ class. The ‘order()’ method is the extra method of the ‘Supplier’ class for sending orders to the supplier (a supplier also has the name and the email address). We need the ‘Supplier’ class because we don’t want to send orders to other contacts (such as family members, friends, or customers) accidentally. Create subclass object with superclass When we create a Supplier object (subclass), the ‘__init__()’ method in the Contact class (superclass) is called automatically. Instances of the Contact class and Supplier class are created in the same way and are added to the same contact list, but treated as objects of different classes. Extending Python’s built-in class with inheritance In order to search contacts in the list, we can add a ‘search()’ method to the Contact class. Actually, the ‘search()’ method should belong to the list, no matter it is a contact list or a shopping list. Python has a built-in ‘list’ class which can be used to create the contact list. If we derive the contact list from the built-in ‘list’ class, then we can use all built-in methods of the ‘list’ class We update our contact list as follows. Extending Python’s built-in class with inheritance Composition The ‘ContactList’ class inherits from the built-in ‘list’ class. The ‘ContactList’ class can use all existing methods of the ‘list’ class The ‘search()’ method is a new method of the ‘ContactList’ class Overriding and super Inheritance allows us to add new attributes and behavior to existing classes, override existing methods, i.e., altering or replacing a method of the superclass with a new method (with the same name) in the subclass. override will only affect the subclass but not the superclass For example, we want to add a phone number for our close friends, Solution 1: define a new method in the Friend class to add the phone attribute Solution 2: totally override ‘__init()__’ method of Contact class Solution 3: partially override ‘__init()__’ method of Contact class Overriding and super Solution 1: does not use inheritance. the ‘phone’ attribute can’t be used by its subclass Solution 2: use inheritance. manually add all existing attributes and the object itself to the all_contact list hard to maintain because of duplicate codes in the super and sub classes (duplicate codes are evil in OOP ) Solution 3: use inheritance. use ‘super()’ method to automatically initialise the existing attributes with superclass __init__ method. Please comment other solutions when you use one add the extra attributes (‘self.phone’) to the Friend class no duplicate code and easy to maintain ☺ Overriding and super Which solution is better? Overriding and super Solution 3 is better: what happens after we call the ‘super()’ method? 1. Gets the instance of the parent object using the keyword ‘super’, i.e., ‘super = Contact(name, email)’; 2. Call ‘__init()__’ method of the parent class with the newly created object, i.e., super.__init(name, email)__; 3. Initialise the new child object with parent attributes and the new attribute, i.e., phone attribute; 4. Return the new child object with all initialised values, i.e., name, email, phone. Note: The‘super()’ method can be made inside any method. If call super() firstly. The superclass’ version will be called first then execute the subclass’ codes. All methods can be modified via overriding and calls to super(). The call to super() can also be made at any point in the method. For example, we may need to manipulate or validate incoming parameters before forwarding them to the superclass. Multiple inheritance issues Python supports multiple inheritance. A subclass that inherits from more than one parent class is able to access functionality from all of them. In practice, multiple inheritance is less useful than it sounds. Many expert programmers recommend against using it. Java does not support multiple inheritance but uses another technique named ‘interface’ to resolve the problem of using methods from different superclasses. We will find out how the multiple inheritance works and why it is not recommended by most programmers. Mixin Mixin is the simplest and most useful form of multiple inheritance. A mixin is a superclass that is meant to be inherited by some other class to provide extra functionality. Mixins are not supposed to work alone. For example, we want to add functionality to our ‘Contact’ class that allows sending an email. Because sending email is a common task that we might want to use on other classes. So, we write a simple mixin class to do the emailing for us. Mixin We define a mixin class, i.e., the MailSender class MailSender class has a function ’send_mail(message)’ Multiple inheritance is used to create a new subclass ‘EmailableContact’. ‘EmailableContact’ class has two parent classes, i.e., Contact and MailSender (mixin) Instances of EmailableContact class can access public members from both parent classes, i.e., sending an email to some contacts. Potential issues with multiple inheritance Multiple inheritance works all right when mixing methods from different classes. But it gets very messy when we call methods on the superclass. Because there are multiple superclasses. How do we know which one to call? How do we know what order to call them in? For example, we want to add a home address to the ‘Friend’ class. Solution 1 (attribute): define a new ‘address’ attribute on the ‘Friend’ class to store the home address. Solution 2 (composition): create a new ‘Address’ class to hold the home address, and then pass an instance of this class to the ‘Friend’ class. Solution 3 (multi-inheritance): create an ‘AddressHolder’ class and use it as the second parent class (mixin) of the ‘Friend’ class Which solution is better? Solution 3: the multi-inheritance solution Because ‘Friend’ class has two superclasses and both of them need to be initialized. How do we do this? We could start with a naïve approach, i.e., calling their ‘__init__’ methods manually Potential issues: 1. A superclass may go uninitialised if we neglect to explicitly call the initializer. 2. A superclass may be called multiple times because of the organization of the class hierarchy. The diamond problem in multiple inheritance The __init__ method from the Friend class first calls __init__ on Contact, which implicitly initializes the object superclass. Then Friend calls __init__ on AddressHolder which also initializes the object superclass again. The parent object class has been set up Twice !!! It could be a disaster in some situations, such as connecting to a database twice for every request. The diamond problem in multiple inheritance The base class’s ‘call_me’ method being called twice. Think about what if this happens on your internet banking when you try to withdraw… A diamond problem solution: super() The 'super’ method saves us again this time. The ‘super’ call is not calling the method on the superclass of LeftSubclass, but calling RightSubclass. Different sets of arguments The situation is more complicated in our ‘Friend’ multiple inheritance example. How to manage different sets of arguments when using super? How can we pass the extra arguments to super to ensure the subsequent calls on other subclasses can receive the right arguments? For example, if the first call to super passes the name and email arguments to Contact.__init__, and Contact.__init__ then calls super. It needs to be able to pass the address-related arguments to the next method, which is AddressHolder.__init__. Different sets of arguments Sadly, the only way to solve this problem is to plan from the beginning. We have to design our base class parameter list to accept keyword arguments from any parameters that are not required by every subclass implementation. We must ensure that method freely accepts unexpected arguments and passes them on to its super class, in case they are necessary to later methods in the inheritance order. Python’s function parameter syntax provides all the tools we need to do this, but it makes the overall code look cumbersome。 *arg and **kwargs in Python Python has two special symbols for passing unspecified arguments: *args (Non-Keyword Arguments): taking in a variable number of arguments. Any number of extra arguments can be tacked on to your current formal parameters (including zero extra arguments) **kwargs (Keyword Arguments): using to pass a keyworded, variable- length argument list. It is a dictionary that maps each keyword to the value that we pass alongside it, i.e. a list of (keyword, value) pairs. *argv examples **kwargs examples Different sets of arguments Here is a ‘proper’ version of the Friend with the multiple inheritance and the keyword arguments. We changed all arguments to keyword arguments by giving them an empty string as a default value. We also ensure a ‘**kwargs’ parameter is included to capture any additional parameters that our particular method doesn’t know what to do with. It passes these parameters up to the next class with the super call. **kwargs collects any keyword arguments passed into the method that were not explicitly listed in the parameter list. These arguments are stored in a dictionary. We can call the dictionary whatever we like, but convention suggests **kwargs. Whe

Use Quizgecko on...
Browser
Browser