Unit III Sequential Programming - Object Oriented Programming Paradigm OOP design principles Object-Oriented Programming (OOP) design principles, often referred to as SOLID principles, are a set of guidelines for writing clean, maintainable, and extensible code in object-oriented programming languages like Java, C++, Python, and more. These principles help developers create software that is easier to understand, modify, and scale. The SOLID acronym stands for five key principles: Single Responsibility Principle (SRP): • • • A class should have only one reason to change. Each class should have a single responsibility or concern. Encourages modular design and separation of concerns. Open/Closed Principle (OCP): • • • Software entities (classes, modules, functions) should be open for extension but closed for modification. New functionality should be added through the extension of existing code rather than changing the existing code. Promotes code reusability and minimizes the risk of introducing bugs when modifying existing code. Liskov Substitution Principle (LSP): • • • • • • Subtypes (derived classes or subclasses) must be substitutable for their base types (parent classes or superclasses) without altering the correctness of the program. Ensures that derived classes adhere to the contract defined by their base classes. Interface Segregation Principle (ISP): Clients should not be forced to depend on interfaces they do not use. Encourages the creation of specific, small, and cohesive interfaces tailored to the needs of the client code. Avoids the problem of "fat" interfaces that contain more methods than a class needs. Dependency Inversion Principle (DIP): • • • High-level modules should not depend on low-level modules; both should depend on abstractions. Abstractions (interfaces or abstract classes) should not depend on details; details should depend on abstractions. Promotes loose coupling between modules, making the system more flexible and easier to maintain. These SOLID principles provide a foundation for designing object-oriented systems that are easier to maintain, extend, and refactor. They promote good practices such as encapsulation, abstraction, and modularization, leading to code that is less prone to bugs and more adaptable to changing requirements. Developers often apply these principles alongside other design patterns and best practices to create well-structured and robust software systems. Object-Oriented Programming is a methodology or paradigm to design a program using classes and objects. It simplifies software development and maintenance by providing some concepts: Object Class Inheritance Polymorphism Abstraction Encapsulation o Any entity that has state and behavior is known as an object. For example, a chair, pen, table, keyboard, bike, etc. It can be physical or logical. An Object can be defined as an instance of a class. An object contains an address and takes up some space in memory. Objects can communicate without knowing the details of each other's data or code. The only necessary thing is the type of message accepted and the type of response returned by the objects. Example: A dog is an object because it has states like color, name, breed, etc. as well as behaviors like wagging the tail, barking, eating, etc. Object o o Class o o Collection of objects is called class. It is a logical entity. A class can also be defined as a blueprint from which you can create an individual object. Class doesn't consume any space. Inheritance o When one object acquires all the properties and behaviors of a parent object, it is known as inheritance. It provides code reusability. It is used to achieve runtime polymorphism. Polymorphism o o o If one task is performed in different ways, it is known as polymorphism. For example: to convince the customer differently, to draw something, for example, shape, triangle, rectangle, etc. In Java, we use method overloading and method overriding to achieve polymorphism. Another example can be to speak something; for example, a cat speaks meow, dog barks woof, etc. Abstraction o o Hiding internal details and showing functionality is known as abstraction. For example phone call, we don't know the internal processing. In Java, we use abstract class and interface to achieve abstraction. Encapsulation o Binding (or wrapping) code and data together into a single unit are known as encapsulation. For example, a capsule, it is wrapped with different medicines.A java class is the example of encapsulation. Java bean is the fully encapsulated class because all the data members are private here. Grouping of Data and Operations: The common properties of an entity can be grouped into a class, and this grouping include both data and operation on the data. This can be consider as abstract data type( ADT). This grouping will lead to creation of instance of these class called objects. CONSTRUCTOR FOR PROGRAM STRUCTRING: This include the three concepts of programming with Procedure, Modules and Classes. Procedure: Here we define procedure corresponding to actions and operaions. This is basically a method followed in imperative style. A program design with procedures can proceed as follows: Behaviour: Define procedures corresponding to what an algorithm does. For example if an algorithm sorts numbers, then define a procedure to sort numbers. Implementation: Hide the details of an algorithm in the procedure body, so the algoritm can be changed without affecting the rest of program. For example we can use quick sort, merge sort or any other technique inside the procedure sort, which will not affect the rest of program. Modules: Module is a collection of declaration typically including both variables and procedures. A module serve as a black box with which the rest of the program interacts through an interface. A program design with modules can proceeds as fillows: Role: Describes the role of a module in general term not in the terms of specificprocedure or variable. Interface: Once the roles are clear, design the module interface. The procedure in the interface define the behaviour of the module. Implementation: Hide design decisions in the private part of a module. The module name can be used as a defined type, but it have to explicitly declared by member function. So, we go to the next method Classes: A class (means class of objects) correspond to a type. The classes can be used as a defined type. Comparison of Approches: Procedure The representation of entries and all details about procedures are accessible through out the program INFORMATION HIDING Module Hide the representation of entries in the entry level of module, which provides public operation for creating entries and so on. Classes Define a class entry, so, entries can be manipulated readily. Information hiding provide the rest of the program from accessing the private part of the object. The main motivation of information hiding is distinguishing behaviour from the implemention. In this view an object can be specified by Abstrct and Concrete specification. An abstract specification tells us the behaviour of an object independent of its implementation ( what an object does) and concrete specification tells us how an object implemented, how its data is laid out and how the data is manipulated by its operations. Consider an example of sorting. The abstract specification tells us to sort a list of elements. The concrete specification tells us wheter the elements are stored using array or linked list. But, the complete information hiding is ideal and rarely attained. Instead of this we emphasis on implementation hiding, which means design a program so that the implementation of an object can be changed with out affecting the rest of the program. Data invariants: A data invarient for an object is a set of property of its local states that holds when ever control is not in the object. For example the data invariant for designin a Queue data structure is: Queue should manipulate elements in FIFO order If front and rear points to a null cell, then Queue is emptyEtc. PROGRAM DESIGN WITH MODULE Modules are useful during progrsm design, even if the programming language does not supportthem. Here the design proceeds from role to implementation to interface. The concept can be illustrated by the example of an expression evaluator. The expression evaluator deals with two distinct representations of expression. Sp we can consider it contain teo modules a Parser and Scanner. The Role of these modules can be defined as follows: Scanner: A lexical analyzer reads the inputs and group them as tokens Parser: A syntax analyzer parses the token stream and evaluate the expression. Interface: This contain varibles to store tokens and methods to scan the elements from the expression. The interface of the module scanner and parser is given below. MODULE Scanner: Type token=( plusminus,times,divide,num,lparen,rparen,semi); Procedure scan //put next token in look ahead and value in look value. Var lookahead: token ; lookvalue: integer; MODULE Parser: Function expr; //parse and evaluate the expression. Implementation This contain the definition for the functions and procedures defined in the interface. This is private part of the modules. The priavte part of the Module Scanner is: Vaar ch: char; Tok:arr[cahr] of token; Procedure getch…… Procedure scaninit…… Function getnum……….. The parser uses grammatical rule for expression evaluation such as E:= E+E/E+T/E-T/T ….The functions factor,terms are used for the implentation of these rules. Program Organization: The progression of Programming with modules as follows: Sequence of Procedures, Nested Procedures and Units. Sequences of Procedures: In this case all procedures are at same level. They can call each other. The main draw back of this method is that the designer cannot identify the related actions. So, if we implement the expression evaluator as sequence of procedures, the designer will lost the concept of two parts Sanner and Parser. The procedures of scanner are visible to all outer procedures. So it reduce implentation hiding. Program Evaluator; Type token=…….; Var lookahead:token; Lookvalue: integer; Ch :cahr Tok: array[char] of token; Procedure getch; Function getnum Procedure scaninit Function factor Function term Function expr Nested Procedure: It is a method to mange the programs with many procedures.Procedure P is said to be nested with Q, if it is defined inside procedure Q, A procedure nested inside another is hidden from the all other outer procedures. So, this technique can be used for grouping and hiding the procedures. The program expression evaluator can be grouped as shown in the following figure. Here, the related procedures are grouped by nesing. Program Evaluator; Type token=…….; Var lookahead:token; Var lookvalue: integer; Procedure scan; Procedure getch; End; Procedure getnum: integer; End; Begin …………….. End; Procedure scaninit; ……………… End; Function expr: integerVar val: Function integer;term:integer Funcion factor: integer Var val: integer; Begin… ....................... end Begin end Modules: A module is grouping of declarations, which can include type variables, and procedures. With modules the design is explicit in the source text. A module has the form: unit name1; interface declaration; implementation declaration; end; The execution of the program starts from a special module called program module. Procedure names will appear in the program, but its codes are private . So the procedure name can be ued as interface whrerere the implementation is hidden. The exaple of Evaluator can be designed by costruction 3 modules: Scanner, Parser and controller. Scaner scans the token, parser appl,ies the grammer and produce the evaluation result. Controller is the program module which control the overall process. Unit scanner; Interface: Type token=…….; Var lookahead:token; Var lookvalue: integer; Procedure scan; Procedure scaninit; Implementation: Procedure scan; ................ End; Unit parser; Interface: uses Scanner function expr; implementation: Function expr: integer Function term:integer Funcion factor: integer Unit controller Interface: Uses parser,scanner; Implementation; Here the keyword uses is used to reuse the properties of another module. Thus the program design Begin….end; with modules allow interface sharing. MODULES AND DEFINED TYPES: Modules permit defined types. That is, with some case defined types can be implemented in a language using modules. Exported and Imported Names: A name is said to be exported if it is explicitly identifiedas a name that can be used outside the constructs. The name exported by one construct can be imported by another. In the above program of Evaluator, the interface of scanner is an exported name. Then the parser module import these exported names by the statement: Unit parser; Interface: uses scanner…. Modula-2, allows selective import of names using the keyword import. Eg: from InOut import ReadInt, WriteInt; will import writeInt and readInt from InOut. Exported Types: Like the names types and associated operattion can be exported. Types exported from modules can imitate defined types. Limitation of Exported Types: Variables has to be initialized explicitly Equity and assignment has to obey the rules of pointers Encapsulation Encapsulation is one of the four fundamental OOP concepts. The other three are inheritance, polymorphism, and abstraction. Encapsulation in Java is a mechanism of wrapping the data (variables) and code acting on the data (methods) together as a single unit. In encapsulation, the variables of a class will be hidden from other classes, and can be accessed only through the methods of their current class. Therefore, it is also known as data hiding. To achieve encapsulation in Java − Declare the variables of a class as private. Provide public setter and getter methods to modify and view the variables values. Example Following is an example that demonstrates how to achieve Encapsulation in Java – /* File name : EncapTest.java */ public class EncapTest { private String name; private String idNum; private int age; public int getAge() { return age; } public String getName() { return name; } public String getIdNum() { return idNum; } public void setAge( int newAge) { age = newAge; } public void setName(String newName) { name = newName; } public void setIdNum( String newId) { idNum = newId; } } The public setXXX() and getXXX() methods are the access points of the instance variables of the EncapTest class. Normally, these methods are referred as getters and setters. Therefore, any class that wants to access the variables should access them through these getters and setters. The variables of the EncapTest class can be accessed using the following program − /* File name : RunEncap.java */ public class RunEncap { public static void main(String args[]) { EncapTest encap = new EncapTest(); encap.setName("James"); encap.setAge(20); encap.setIdNum("12343ms"); System.out.print("Name : " + encap.getName() + " Age : " + encap.getAge()); } } This will produce the following result − Output Name : James Age : 20 Benefits of Encapsulation The fields of a class can be made read-only or write-only. A class can have total control over what is stored in its fields.