10.2. Support for Object Oriented Programming
Support for Object-Oriented Programming
- What do we study in this chapter?
- Object-oriented programming (OOP)
- Design issues for OOP
- Language examples
- Implementation of object-oriented constructs
Object-Oriented Programming (OOP)
Three major language features
Abstract data types
Inheritance (central theme in OOP)
Polymorphism
Object-oriented concepts (Inheritance)
Productivity increases can come from reuse
ADTs are difficult to reuseโalways need changes
All ADTs are independent and at the same level
Inheritance allows new classes defined in terms of existing ones
i.e., by allowing them to inherit common parts
Inheritance addresses both of the above concerns
Reuse ADTs after minor changes and define classes in a hierarchy
ADTs are usually called classes
Class instances are called objects
Subclass or derived class โ inherits from parent (superclass)
Subprograms that operate on (belong to) objects = methods
Variables encapsulated by objects = instance variables
Method calls โ sometimes called messages
Collection of methods of an object โ its message protocol or message interface
๊ฐ์ฒด๋ ๋จ์ํ ํจ์๋ฅผ ์คํํ๋ ๊ฒ ์๋๋ผ, ๋ฉ์์ง๋ฅผ ๋ฐ๊ณ ๊ฑฐ๊ธฐ์ ๋ฐ์ํ๋ ์กด์ฌ๋ก ์ทจ๊ธ๋๊ธฐ ๋๋ฌธ
๊ฐ์ฒด๋ ์์ ์ด ์ดํดํ ์ ์๋ ๋ฉ์์ง(= ๋ฉ์๋ ์ด๋ฆ)๋ง ์ฒ๋ฆฌํ ์ ์์
Messages have method name, destination object
Generally default = inherit all from parent
Inheritance can be complicated by access controls
Class can hide entities from subclasses
Class can hide entities from its โclientsโ
Some languages can hide entities from clients, but let subclasses see them
Subclass can modify inherited method
Can override default (inherited) โ overrides the parentโs method
Object-oriented concepts (Subclass differences from parent)
Three ways a class can differ from its parent:
- The parent class can define some of its variables or methods to have private access, which means they will not be visible in the subclass
- The subclass can add variables and/or methods to those inherited from the parent
- The subclass can modify the behavior of one or more of its inherited methods
Object-oriented concepts
There are two kinds of variables in a class:
Class variables - one/class
Instance variables - one/object
There are two kinds of methods in a class:
Class methods โ accept messages to the class
Instance methods โ accept messages to objects
Single vs. Multiple Inheritance
Single inheritance โ all OO languages
Multiple inheritance
Most OO languages
Sometimes problematic โ what to inherit when there is a conflict?
Disadvantages for reuse
Creates interdependencies among classes -> complicates maintenance
May be functionally useful, but not logical, for a class to inherit from another
Dynamic Binding
- Since a hierarchy of classes exist, can exploit for polymorphism
- Polymorphic variable: can hold objects of a class or any of its descendants
- Top of object hierarchy can even point to any object
- Dynamic binding:
- Some methods of some subclasses may override a parentโs
- Which method of which class is called is decided at run-time
- Benefits:
- The usual ones for polymorphism
- Also: easy to extend software system during development and maintenance
- Abstract (virtual) method: only defines a protocol, not a definition
- Abstract class:
- Includes at least one abstract method
- Cannot be instantiated
Design Issues for OOP Languages
- Is everything an object? (Exclusivity of objects)
- Subclasses = subtypes?
- Single or multiple inheritance?
- Allocating and deallocating objects
- Dynamic and static binding
- Nested classes?
- Object initialization
- Exclusivity of objects
- Some languages: everything is an object โ e.g., Ruby, Smalltalk
- Advantage: elegance, purity, homogeneity of all data structures
- Disadvantage: can be slow for simple objects
- Other languages: objects are added to a complete typing system โ Lisp, Python,โฆ
- (๋ชจ๋ ๊ฒ ๊ฐ์ฒด์ฒ๋ผ ๋ณด์ด๋ ๋ด๋ถ์ ์ผ๋ก ์ผ๋ถ๋ ์๋)
- Advantage - fast operations on simple objects
- Disadvantage - results in a confusing type system (two kinds of entities)
- Other languages: use imperative-style typing system for primitives, but everything else is an object โ Java, Swift, โฆ
- ๊ฐ์ฒด/๊ธฐ๋ณธํ ๊ตฌ๋ถ ๋ช ํ
- Advantage - fast operations on simple objects and a relatively small typing system
- Disadvantage - still some confusion because of the two type systems
- Are (sub)classes (sub)types?
- Most OO languages: yes
- Basically: does an โisaโ relationship hold between parent class and subclass?
- "is-a" ๊ด๊ณ๋ ์ธํฐํ์ด์ค์ ๊ธฐ๋ฐํ ํ์ ๊ด๊ณ
- If so, then instances of subclass must behave the same (more or less) as instances of the parent (์๋ธํ์ ์ ์์ ํ์ ์ฒ๋ผ ํ๋ํ ์ ์์ด์ผ ํจ)
- Subclass can only:
- Add variables and methods
- Override methods in โcompatibleโ ways
- Also has some implication for ontology the programmer has in mind
- Subclasses are made for ontological reasons, not just for functionality and reuse
- E.g., make airplane subclass of vehicle, not bird โ even though โflyโmethod could be inherited in the latter
- ๊ธฐ๋ฅ ์ฌ์ฌ์ฉ์ด ์๋ ๊ฐ๋ ์ ๊ด๊ณ(์จํจ๋ก์ง) ์ค์ฌ ์ค๊ณ
- Single or multiple inheritance?
- Advantages of multiple inheritance:
- Convenient โ methods, variables from multiple sources
- Ontologically-useful โ aircraft is a vehicle, flying-object, bird is a animal, flying-object
- Disadvantages:
- Complexity of language, implementation (e.g., handling name collisions)
- Potential inefficiency โ increased cost of dynamic binding (search problem)
- Allocation and Deallocation of Objects
- From where are objects allocated?
- If treated as other ADTs, can be allocated anywhere: run-time stack, heap (via new, e.g.)
- If heap-dynamic only (e.g., Java, Lisp, Python,โฆ)
- Heap-dynamic only์ ์ฅ์
- References can be uniform via pointer/reference variable
- ๊ฐ์ฒด ๋ณ์๋ ํญ์ ํฌ์ธํฐ ๋๋ ์ฐธ์กฐ(reference) ์ญํ -> ์ด๋ค ํ์ ์ด๋ ๊ฐ์ ๋ฐฉ์์ผ๋ก ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ๊ฐ๋ฅ
- Simplifies assignment; dereferencing can be implicit
- ํ ๋น, ์ ๋ฌ, ๋ณต์ฌ ๋ฑ์์ ์ผ๊ด๋ ์ฒ๋ฆฌ ๊ฐ๋ฅ -> ๋ณต์กํ ๋ณต์ฌ(= ๊ฐ ๋ณต์ฌ vs ์ฐธ์กฐ ๋ณต์ฌ) ๋ฌธ์ ์ค์ด๋ฆ
- Allocation and DeAllocation of Objects
- If stack-dynamic only: can -> object slicing
- Object of subclass B may be larger than one of its parent class A
- Suppose subroutine expects instance of Aโฆ
- โฆpass instance of Bโฆ
- โฆnot enough room allocated, some instance variables not copied โor worse
- Kind of unavoidable with call-by-value and polymorphism by classes
- Is deallocation explicit or implicit?
- Dynamic and Static Binding
- ๋ฉ์์ง(๋ฉ์๋ ํธ์ถ)๊ฐ ์ค์ ๋ก ์ด๋ค ๋ฉ์๋ ๊ตฌํ์ฒด์ ์ฐ๊ฒฐ๋๋์ง ๊ฒฐ์ ํ๋ ์์
- ์ฆ,
obj.method()๋ฅผ ํธ์ถํ์ ๋, ์ด๋คmethod()๊ฐ ์คํ๋ ์ง๋ฅผ ์ธ์ ๊ฒฐ์ ํ๋๋์ ๋ฌธ์ - Should all binding of messages to methods be dynamic?
- If none are, you lose the advantages of dynamic binding
- If all are, it is inefficient
- Maybe the design should allow the user to specify
- Dynamic Binding
- ์ฅ์ : ๋คํ์ฑ(polymorphism) ๊ตฌํ ๊ฐ๋ฅ ์๋ก์ด ํด๋์ค๋ฅผ ์ถ๊ฐํด๋ ๊ธฐ์กด ์ฝ๋ ๋ณ๊ฒฝ ์์ด ํ์ฅ ๊ฐ๋ฅ
- ๋จ์ : ๋ฐํ์ ๋น์ฉ ์ฆ๊ฐ (vtable, lookup ๋ฑ) ์์ธก/์ต์ ํ ์ด๋ ค์
- Nested classes
- Some languages allow it (e.g., Java, Python, Ruby), others donโt (Lisp)
- Why?
- Sometimes only one class (e.g., Tree) needs a particular new class (e.g., Node)
- Defining Node outside the Tree class -> clutters the object system, may cause name clashes, etc.
- Avoid this if we nest Node inside Tree class
- Sometimes nesting is inside a subprogram rather than directly in class (ํจ์ ๋ด๋ถ์์ ํด๋์ค ์ ์๋ ๊ฐ๋ฅ)
- Issue: which parts of the nested class should be visible to parent and vice versa?
- Nested class์ outer class๋ ์๋ก์ ๋ฉค๋ฒ์ ์ ๊ทผํ ์ ์๋๊ฐ?
- Initialization of Objects
- Are objects initialized to values when they are created?
- Implicit or explicit initialization
- How are parent class members initialized when a subclass object is created?
Support for OOP in Smalltalk
- Pure OO language -> everything is an object
- All objects have local memory (to process, communicate with other object, inherit from ancestors)
- Cannot be nested
- All computation is through objects sending messages to objects
- [EX]
x + 7: sending+message tox(object) with7(parameter), then return a new object - No imperative structure (๊ฐ์ฒด์ ๋ฉ์์ง๋ก ์ ์ด ์์ฒญ)
- Heap-dynamic objects
- Implicit deallocation
- Constructor must be explicitly called
- Inheritance
- A Smalltalk subclass inherits all of the instance variables, instance methods, and class methods of its superclass
- All subclasses are subtypes (nothing can be hidden)
- Overriding is possible (method in ancestor is hidden, accessed by super)
- No multiple inheritance
- All messages: method binding is dynamic
- Type checking: only dynamic type checking
- Only error is when object cannot handle a message (duck typing)
- Variables in Samlltalk are not typed (can be bound to any object, support dynamic polymorphism)
- Evaluation
- Simple, regular syntax
- Good example of powerful, small language
- Slow compared to compiled imperative languages
- Dynamic binding allows type errors to go undetected until run time
- Introduced the idea of a GUI
- Greatest legacy โ advanced/established OOP
"Smalltalk Example Program"
"The following is a class definition, instantiations of which can draw equilateral polygons of any number of sides"
class name polygon
superclass Object
instance variable names numSides
sideLength
"Class methods"
"Create an instance"
new
^ super new getPen
"Get a pen for drawing polygons"
getPen
ourPen <- Pen new defaultNib: 2
"Instance methods"
"Draw a polygon"
draw
numSides timesRepeat: [ourPen go: sideLength;
turn: 360 // numSides]
"Set length of sides"
length: len
sideLength <- len
"Set number of sides"
sides: num
numSides <- num
Support for OOP in C++
- General Characteristics:
- Evolved from C and SIMULA 67
- Among the most widely used OOP languages
- Mixed typing system
- Objects can be static, stack dynamic and heap dynamic
- Explicit deallocation by new
- Constructors and destructors (implicitly called)
- Elaborate access controls to class entities
- Inheritance
- A class need not be the subclass of any class
- Object should be initialized (including inherited data member)
- Parent constructor is implicitly called
- Access controls for members are
- Private (visible only in the class and friends) (disallows subclasses from being subtypes)
- Public (visible in subclasses and clients)
- Protected (visible in the class and in subclasses, but not clients)
- In addition, the subclassing process can be declared with access controls (private or public), which define potential changes in access by subclasses
- Private derivation - inherited public and protected members are private in the subclasses
- Public derivation - public and protected members are also public and protected in subclasses
class derived_class_name : derivation_mode base_class_name
{data member and member function declarations};
//derivation_mode can be either public or private
class base_class {
private:
int a;
float x;
protected:
int b;
float y;
public:
int c;
float z;
};
- Private-derived subclasses cannot be subtypes -> is-a relationship would be broken
class subclass_1 : public base_class { โฆ };
// In this one, b and y are protected and
// c and z are public
class subclass_2 : private base_class { โฆ };
// In this one, b, y, c, and z are private,
// and no derived class has access to any
// member of base_class
- Reexportation in C++
- A member that is not accessible in a subclass (because of private derivation) can be declared to be visible there using the scope resolution operator (
::), e.g.,
class subclass_3 : private base_class {
base_class :: c;
โฆ
}
- One motivation for using private derivation
- A class provides members that must be visible, so they are defined to be public members; a derived class adds some new members
- But does not want its clients to see the members of the parent class, even though they had to be public in the parent class definition
- ๊ธฐ๋ฅ์ ๊ตฌํ์ ๋ถ๋ชจ ํด๋์ค์ ๋๋, ์ธ๋ถ์๋ ์ ํ๋ ์ธํฐํ์ด์ค๋ง ๋ ธ์ถํ๊ณ ์ถ์ ๋ ์ ์ฉ
- ์บก์ํ(Encapsulation) ์์น์ ์ ์งํ๋ฉด์๋, ๋ด๋ถ ๊ตฌํ์ ์ฌ์ฌ์ฉํ ์ ์์
class single_linked_list {
private:
class node {
public:
node *link;
int contents;
};
node *head;
public:
single_linked_list() {head = 0};
void insert_at_head(int);
void insert_at_tail(int);
int remove_at_head();
int empty();
};
class stack_2 : private single_linked_list {
public:
stack_2() {}
void push(int value) {
single_linked_list :: insert_at_head(value);
}
int pop() {
return single_linked_list :: remove_at_head();
}
single_linked_list:: empty();
};
insert_at_tailcan be protected from stack by Private derivation- Multiple inheritance
- Two inherited members with the same name
- Both can be referenced using the scope resolution operator (
::)
class Thread { ... }
class Drawing { ... }
class DrawThread : public Thread, public Drawing { โฆ }
- Overriding
- Overriding methods must have exactly the same parameter profile as the overridden method
- Any difference in the parameter -> considered a new method
- Dynamic Binding
- Virtual method: can be called through polymorphic variables and dynamically bound to messages
- Pure virtual function has no definition at all
- Class that has at least one pure virtual function is an abstract class
- If subclass of abstract class does not redefine pure virtual function -> It also abstract class
class Shape {
public:
virtual void draw() = 0;
...
};
class Circle : public Shape {
public:
void draw() { ... }
...
};
class Rectangle : public Shape {
public:
void draw() { ... }
...
};
class Square : public Rectangle {
public:
void draw() { ... }
...
};
Square* sq = new Square;
Rectangle* rect = new Rectangle;
Shape* ptr_shape;
ptr_shape = sq; // points to a Square
ptr_shape ->draw(); // Dynamically bound to draw in Square
rect->draw(); // Statically bound to draw in Rectangle
// If objects are allocated from the stack, it is quite different
Square sq; // Allocates a Square object from the stack
Rectangle rect; // Allocates a Rectangle object from the stack
rect = sq; // Copies the data member values from sq object
rect.draw(); // Calls the draw from Rectangle
- Evaluation
- C++ provides extensive access controls (unlike Smalltalk)
- C++ provides multiple inheritance
- In C++, the programmer must decide at design time which methods will be statically bound and which must be dynamically bound
- Smalltalk type checking is dynamic (flexible, but somewhat unsafe)
- Variable in Smalltalk is typeless
- Static binding is faster!
- Because of interpretation and dynamic binding, Smalltalk is ~10 times slower than C++
Support for OOP in Objective-C
- Like C++, Objective-C adds support for OOP to C
- Design was at about the same time as that of C++
- Largest syntactic difference: method calls are messages (similar to Smalltalk)
- Interface section of a class declares the instance variables and the methods
- Implementation section of a class defines the methods
- No class variable directly (static global variable in implementation can be used)
- Classes cannot be nested
- Single inheritance only
- Every class must have a parent
NSObjectis the base class
@interface myNewClass: NSObject { โฆ }
โฆ
@end
- For universally needed operations such as
allocandinit - Any method that has the same name, same return type, and same number and types of parameters as an inherited method overrides the inherited method
- ์ด๋ฆ, ๋ฐํํ, ๋งค๊ฐ๋ณ์ ๋ชฉ๋ก์ด ์์ ํ ์ผ์นํ ๊ฒฝ์ฐ
- An overriden method can be called through
super - All inheritance is public derivation (unlike C++)
- Objective-C has two approaches besides subclassing to extend a class
- A category is a secondary interface of a class that contains declarations of methods
- ์นดํ ๊ณ ๋ฆฌ๋ ๊ธฐ์กด ํด๋์ค์ ์๋ก์ด ๋ฉ์๋๋ฅผ ์ถ๊ฐํ ์ ์๋๋ก ํ๋ ๊ตฌ์กฐ
- ์ธ์คํด์ค ๋ณ์๋ ์ถ๊ฐํ ์ ์์ (์ค์ง ๋ฉ์๋๋ง ์ถ๊ฐ ๊ฐ๋ฅ)
- ์๋ ํด๋์ค์ ์์ค ์ฝ๋๋ฅผ ์์ ํ์ง ์๊ณ ๋ ํ์ฅ ๊ฐ๋ฅ
#import "Stack.h"
@interface Stack (StackExtend)
-(int) secondFromTop;
-(void) full;
@end
- Name of this category is
StackExtend - A category is a mixin โ its methods are added to the parent class
- Provide some of the benefits of multiple inheritance
- Parent class need not be mentioned
- The implementation of a category is in a separate implementation:
@implementation Stack (StackExtend)
- The other way to extend a class: protocols
- A protocol is a list of method declarations (like Javaโs interfaces)
- Protocol์ ํด๋์ค๊ฐ ๊ตฌํํด์ผ ํ ๋ฉ์๋ ๋ชฉ๋ก์ ์ ์ํ๋ ์ผ์ข ์ ๊ณ์ฝ
- Related to abstract class in C++
@protocol MatrixOps
-(Matrix *) add: (Matrix *) mat;
-(Matrix *) subtract: (Matrix *) mat;
@optional
-(Matrix *) multiply: (Matrix *) mat;
@end
MatrixOpsis the name of the protocol- The
addandsubtractmethods must be implemented by class that uses the protocol - A class that adopts a protocol must specify it
@interface MyClass: NSObject <YourProtocol>- Dynamic Binding
- Different from other OOP languages โ a polymorphic variable is of type
id - An
idtype variable can reference any object - The run-time system keeps track of the type of the object that an
idtype variable references - If a call to a method is made through an
idtype variable, the binding to the method is dynamic
// Create the objects
Circle *myCircle = [[Circle alloc] init];
Square *mySquare = [[Square alloc] init];//Set the id to reference the circle and draw it
shapteRef = myCircle;
[shapeRef draw];
// Initialize the objects
[myCircle setCircumference: 5];
[mySquare setSide: 5];// Set the id to reference the square
shapeRef = mySquare;
[shapeRef draw];
// Create the id variable
id shapeRef;
- Evaluation
- Support is adequate, with the following deficiencies:
- There is no way to prevent overriding an inherited method
final๊ฐ์ ํค์๋๊ฐ ์์ (Java์๋ ์์)- The use of
idtype variables for dynamic binding is overkill โ these variables could be misused - ์ปดํ์ผ ํ์ ํ์ ์ฒดํฌ๊ฐ ๋ถ๊ฐ -> ์ค์๋ก ์๋ชป๋ ๋ฉ์์ง๋ฅผ ๋ณด๋ผ ์ ์์
- ์ฝ๋์ ์์ ์ฑ๊ณผ ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง ์ ์์
- Categories and protocols are useful additions
- Even though there is no exact multiple inheritance
- category: ํด๋์ค์ ๋ฉ์๋๋ฅผ ์ถ๊ฐํ ์ ์๊ฒ ํด์ฃผ๋ ๊ตฌ์กฐ (mixin ์ ์ฌ)
- protocol: ์ธํฐํ์ด์ค ์ ์๋ฅผ ์ํ ๊ตฌ์กฐ (Java์ interface์ ์ ์ฌ)
Support for OOP in Java
- Because of its close relationship to C++, focus is on the differences from that language
- General characteristics
- All data are objects except the primitive types
- All primitive types have wrapper classes that store one data value
- Primitive values are implicitly coerced (boxing)
- All classes are descendant of Object class
- All objects are heap-dynamic, are referenced through reference variables, and most are allocated with
new - Inheritance
- Methods can be
final(cannot be overriden) - Bindings of method calls to the methods of the subclass are statically bound
- Not support the private and protected derivations of C++
- Subclasses should be subtypes
- All of the methods of
Vector(parent) were also visible in theStackclass in Java collection - ->
Stackin Java collection have various operations (not common in generalStack)
class Animal {
String name;
int numberOfLegs;
public final void birth(){...}
}
class Dog extends Animal {
String type;
}
- Single inheritance supported only, but there is an abstract class category that provides some of the benefits of multiple inheritance (interface)
- An interface can include only method declarations and named constants
- Cannot contain constructors or nonabstract methods
- A class does not inherit an interface; it implements any number of interface
- All of the methods must be implemented
- To simulate multiple inheritance
- Inherit a class + implement a interface
- Interface provides another kind of polymorphism
- Problem with multiple inheritance can be avoided (the same name with the same protocol)
- Class need not reimplement that method having the same name and protocol
- [Variable name conflict] Completely avoided because there is not variable definition in interface
- Interface != multiple inheritance
- Because interfaces can be treated as types
- Interfaces provide no code reuse
- One problem with interfaces
- If a class implements two interfaces having the same name (and protocol), no way to implement both
- [EX]
public interface Animal {
public abstract void bark();
}
public class Dog implements Animal{
@Override
public void bark() {
System.out.println("Woof woof!");
}
}
public class Cat implements Animal{
@Override
public void bark() {
System.out.println("Meow Meow!");
}
}
- Dynamic binding
- In Java, all messages are dynamically bound to methods, unless the method is
final(i.e., it cannot be overriden, therefore dynamic binding serves no purpose) - Static binding is also used if the methods is static or private both of which disallow overriding
- Nested Classes
- All are hidden from all classes in their package, except for the nesting class
- Nonstatic classes nested directly are called inner classes
- An innerclass can access members of its nesting class
- Each innerclass has implicit pointer to instance of nesting class
- A static nested class cannot access members of its nesting class
- Static nested class does not have implicit pointer
- Members of the inner class, even the private members, are accessible in the outer class
- A local nested class is defined in a method of its nestingclass
- No access specifier is used
- Their scope is always limited to their nesting class
- Evaluation
- Design decisions to support OOP are similar to C++
- No support for procedural programming
- No parentless classes
- Dynamic binding is used as โnormalโ way to bind method calls to method definitions
- Uses interfaces to provide a simple form of support for multiple inheritance
Support for OOP in C#
- General characteristics
- Support for OOP similar to Java
- Includes both classes and structs
- Classes are similar to Javaโs classes
- structs are less powerful stack-dynamic constructs (e.g., no inheritance)
- Inheritance
- Uses the syntax of C++ for defining classes
public class NewClass : ParentClass { ... }- A method inherited from parent class can be replaced in the derived class by marking its definition with
new new๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์, ๋ฉ์๋๋ ์ค๋ฒ๋ผ์ด๋๋์ง ์๊ณ ์ ์ ์ผ๋ก ๋ฐ์ธ๋ฉ๋จ, ๊ฐ๋ฐ์์๊ฒ ์๋๋ฅผ ๋ช ํํ ํํํ๋ผ๊ณ ์๊ตฌ
class Parent {
public void Greet() {
Console.WriteLine("Hello from Parent");
}
}
Parent p = new Child();
p.Greet(); // ์ถ๋ ฅ: Hello from Parent
Child c = new Child();
c.Greet(); // ์ถ๋ ฅ: Hello from Child
class Child : Parent {
public new void Greet() { // new๋ก ๋ถ๋ชจ ๋ฉ์๋ ์จ๊น
Console.WriteLine("Hello from Child");
}
}
- The parent class version can still be called explicitly with the prefix
base: base.Draw()- Dynamic binding
- To allow dynamic binding of method calls to methods:
- The base class method is marked
virtual - The corresponding methods in derived classes are marked
override
public class Shape {
public virtual void Draw() { ... }
...
}
public class Rectangle : Shape {
public override void Draw() { ... }
...
}
public class Circle : Shape {
public override void Draw() { ... }
...
}
public class Square : Rectangle {
public override void Draw() { ... }
...
}
- Abstract methods are marked
abstractand must be implemented in all subclasses - Abstract classes cannot be instantiated
- All C# classes are ultimately derived from a single root class,
Object Objectclass defines a collection of methods, includingToString,Finalize, andEquals- Nested classes
- A C# class that is directly nested in a nesting class behaves like a Java static nested class
- C# does not support nested classes that behave like the non-static classes of Java
- ๋ช ์์ ์ฐธ์กฐ ํ์
- Evaluation
- C# is a relatively recently designed C-based OO language
- The differences between C#โs and Javaโs support for OOP are relatively minor
structin C# (not in Java)- Simpler than C++ for OOP
Support for OOP in Ada 95+
- General Characteristics
- OOP was one of the most important extensions to Ada 83
- Supporting inheritance and dynamic binding
- Encapsulation container is a package that defines a tagged type
- A tagged type is one in which every object includes a tag to indicate during execution its type (the tags are internal)
- Tagged types can be either private types or records
- No constructors or destructors are implicitly called
- Inheritance
- Subclasses can be derived from tagged types
- New entities are added to the inherited entities by placing them in a record definition
- All subclasses are subtypes
- Does not allow one to prevent entities of the parent class from being included in the derived class
- No support for multiple inheritance
- A comparable effect can be achieved using generic classes
package Person_Pkg is
type Person is tagged private;
procedure Display(P : in out Person);
private
type Person is tagged
record
Name : String(1..30);
Address : String(1..30);
Age : Integer;
end record;
end Person_Pkg;
with Person_Pkg; use Person_Pkg;
package Student_Pkg is
type Student is new Person with
record
Grade_Point_Average : Float;
Grade_Level : Integer;
end record;
procedure Display (St: in Student);
end Student_Pkg;
P1 : Person;
S1 : Student;
Fred : Person := (To_Unbounded_String("Fred"),
To_Unbounded_String("321 Mulberry Lane"), 35);
Freddie : Student :=
(To_Unbounded_String("Freddie"),
To_Unbounded_String("725 Main St."),
20, 3.25, 3);
P1 := Freddie; // Legal because Student is a subtype of Person
// Grade_Point_Average and Grade_Level are ignored -> object slicing
S1 := (Fred, 3.05, 2); // Legal
// Note: Display is being overridden from Person_Pkg
- Dynamic Binding
- Dynamic binding is done using polymorphic variables called classwide types
- For the tagged type
Person, the classwide type isPerson'class - Other bindings are static
- Any method may be dynamically bound
- Purely abstract base types can be defined in Ada 95 by including the reserved word
abstract
procedure Display_Any_Person(P: in Person) is
begin
Display(p);
end Display_Any_Person;
โฆ
with Person_Pkg; use Person_Pkg;
with Student_Pkg; use Student_Pkg;
P : Person;
S : Student;
Pcw : Personโclass; -- A classwide variable
โฆ
Pcw := P;
Display_Any_Person(Pcw); -- Calls the Display in Person
Pcw := S;
Display_Any_Person(Pcw); -- Calls the Display in Student
package Base_Pkg is
type T is abstract tagged null record;
procedure Do_It (A : T) is abstract;
end Base_Pkg;
- Child Packages
- A child package is logically (possibly physically) nested inside another package
- Solves the problem of packages becoming physically too large
- if separate, they are called child library packages
- Declarations of the private child package are not visible to the nesting package body
- Even the private parts of the parent package are visible to the child package
- A child package is an alternative to class derivation (like protected)
- A child library package can be added any time to a program
- Evaluation
- Ada offers complete support for OOP
- C++ offers better form of inheritance than Ada
- Ada includes no initialization of objects (e.g., constructors)
- Dynamic binding in C-based OOP languages is restricted to pointers and/or references to objects; Ada has no such restriction and is thus more orthogonal
Support for OOP in Ruby
- General Characteristics
- Everything is an object
- All computation is through message passing
- Class definitions are executable, allowing secondary definitions to add members to existing definitions
- Method definitions are also executable
- All variables are type-less references to objects
- Access control is different for data and methods
- It is private for all data and cannot be changed (accessor methods must be defined if needed)
- Methods can be either public, private, or protected
- Method access is checked at runtime
- Getters and setters can be defined by shortcuts (i.e. by
attr_reader,attr_writer) - Inheritance
- Access control to inherited methods can be different than in the parent class
- Subclasses are not necessarily subtypes
- Mixins can be created with modules, providing a kind of multiple inheritance
- Dynamic Binding
- All variables are typeless and polymorphic
- Evaluation
- Does not support abstract classes
- Does not fully support multiple inheritance
- -> achieved by modules, mixin, etc..
- Access controls are weaker than those of other languages that support OOP
Implementing OO Constructs
- Two interesting and challenging parts
- Storage structures for instance variables
- Dynamic binding of messages to methods
- Instance Data Storage
- Class instance records (CIRs) store the state of an object
- Static (built at compile time)
- Every class has its own CIR
- If a class has a parent, the subclass instance variables are added to the parent CIR
- Because CIR is static, access to all instance variables is done as it is in records
- Using constant offsets from the beginning of the CIR instance -> efficient
- Dynamic Binding of Methods Calls
- Methods in a class that are statically bound need not be involved in the CIR
- Methods that will be dynamically bound must have entries in the CIR
- Such entries have a pointer to code of method (set at object creation time)
- Calls to dynamically bound methods can be connected to the corresponding code thru a pointer in the CIR
- Drawback: every instance (with dynamically bound methods) would need to store pointers
- The storage structure is sometimes called virtual method tables (vtable)
- List of such methods are stored
- Method calls can be represented as offsets from the beginning of the vtable
- [EX] Java (single inheritance)
- Method pointer for the area method in Bโs vtable points to the code for Aโs area method
- Pointers for draw and sift in Bโs vtable point to Bโs draw and sift
- [EX] Java (multiple inheritance)
- There must be at least two different views available in the CIRโone for each of the parent classes, one of which includes the view for the subclass, C
Support for Object-Oriented Programming
- Summary
- OO programming involves three fundamental concepts: ADTs, inheritance, dynamic binding
- Major design issues: exclusivity of objects, subclasses and subtypes, type checking and polymorphism, single and multiple inheritance, dynamic binding, explicit and implicit de-allocation of objects, and nested classes
- Smalltalk is a pure OOL
- C++ has two distinct type systems (hybrid)
- Java is not a hybrid language like C++; it supports only OOP
- C# is based on C++ and Java
- Ruby is a relatively recent pure OOP language; provides some new ideas in support for OOP
- Implementing OOP involves some new data structures

