Sie sind auf Seite 1von 40

Myung Ho Kim, Ph.D.

Understanding Professor, Chung-Ang


University
Object-Oriented Programming enkiluv@cau.ac.kr
High-Level Languages
Abstractions around von-Neumann architecture
 Variable: Memory cell
 Operator: CPU (ALU)
 Assignment: Modification of the content of memory cell(s)
 Control structures (if, while, …): CPU (CU)
Abstraction? Abstraction!
Separate essentials (what) from the details (how)
Emphasize essentials while suppressing details
Building higher-level abstractions
 Procedural abstraction
 Data abstraction
 Object-orientation
Procedural Abstraction
Combine statements and making them a reusable
entity
 E.g. C functions, Python methods, Lisp/Scheme lambda
What
 Usage: name, parameters
 The effect or function the procedure performs
How
 Algorithms and data structures
# Add numbers from 1 up to n
def sigma(n):
num = n*(n+1)
return int(num/2)
print(sigma(10))
Data Abstraction
Encapsulate data structures and related operations
in a single syntactic entity, and force clients to use
operations only to access the data structures
What
 Operations
 Meanings of individual operations and their combinations
How
 Algorithms and Data structures
Data types defined in this manner is called Abstract
Data Types (ADTs)
Abstract Data Type “SchoolMember”
datatype SchoolMember:
string name
Date birthdate
def init(name, date):
self.name = name
self.birthdate = date
def age():
return now.Year – birthdate.Year
def greet():
print(“Hello, I am ” + name + “!”)
end Person

JY = SchoolMember().init(“JY”, Date(“1970-09-21”))
print(JY.age())
JY.greet()
Problems of Pure Abstract Data Types
All ADTs are independent and at the same level
Can we define new types in terms of existing ones?
Can we treat hierarchically structured types as
compatible ones?
Can we redefine operations while keeping the
interface intact?
Teacher and Student Example
Teacher Student
name, birthdate, lecture name, birthdate, id_no
name, age, teaches, name, age, ID_no,
greet greet
Teacher and Student in “C” (V1)
typedef struct { typedef struct {
char name[NAMELEN]; char name[NAMELEN];
Date birthdate; Date birthdate;
char lecture[NAMELEN]; int id_no;
} Teacher; } Student;
Teacher newTeacher(char *name, Student newStudent(char *name,
Date birthdate, char *teaches) { Date birthdate, int id_no) {
Teacher teacher; Student student;
strcpy(teacher.name, name); strcpy(student.name, name);
teacher.birthdate = birthdate; student.birthdate = birthdate;
strcpy(teacher.lecture, teaches); student.id_no = id_no;
return teacher; return student;
} }
int Teacher_Age(Teacher teacher) { int Student_Age(Student student) {
return Now().year – return Now().year – student.birthdate.year;
teacher.birthdate.year; }
} char *Student_Greet(Student student) {
char *Teacher_Greet(Teacher teacher) { char *buf = (char *)malloc(BUFSIZ);
char *buf = (char *)malloc(BUFSIZ); sprintf(buf, "Name: %s, Age: %d, ID_no: %d",
sprintf(buf, "Name: %s, Age: %d, student.name, Student_Age(student),
Teaches: %s", student.id_no);
teacher.name, return buf;
Teacher_Age(teacher), }
teacher.lecture);
return buf;
}
Teacher and Student (Cont’d)
Teacher Student
name, birthdate, lecture name, birthdate, id_no
name, age, teaches, name, age, ID_no,
greet greet

May we build an array for a collection of teachers


and students and sort its elements according to the
age or name?
Teacher and Student in “C” (V2)
typedef enum { TEACHER, STUDENT; } member_type; int Member_Age(Member member) {
typedef struct { return Now().year –
char name[NAMELEN]; member.birthdate.year;
Date birthdate; }
member_type klass;
union { char *Member_Greet(Member member) {
char lecture[NAMELEN]; int id_no; char *buf = (char *)malloc(BUFSIZ);
} specific; char *etc = (char *)malloc(BUFSIZ/2);
} Member; sprintf(buf, "Name: %s, Age: %d",
Member newMember(char *name, Date birthdate) { member.name, Member_Age(member));
Member member; switch (member.klass) {
strcpy(member.name, name); case TEACHER:
member.birthdate = birthdate; sprintf(etc, ", Teaches: %s",
return member; member.specific.lecture);
} break;
Member newTeacher(char *name, Date birthdate, case STUDENT:
char *teaches) { sprintf(etc, ", ID_no: %d",
Member teacher = newMember(name, birthdate); member.specific.id_no);
teacher.klass = TEACHER; break;
strcpy(teacher.specific.lecture, teaches); }
return teacher; strcat(buf, etc);
} free(etc);
Member newStudent(char *name, Date birthdate, return buf;
int id_no) { }
Member student = newMember(name, birthdate);
student.klass = STUDENT;
student.specific.id_no = id_no;
return student;
}
Teacher and Student in “C” (V2, Cont’d)
/* Age comparator */
int ageComp(const void *e1, const void *e2)
{
Member m1 = *((Member *)e1);
Member m2 = *((Member *)e2);
return Member_Age(m1) - Member_Age(m2);
}
int main(int argc, char *argv[]) {

Member members[10];
int m_count = 0;
members[m_count++] = newTeacher(…);
members[m_count++] = newStudent(…);
qsort(members, m_count, sizeof(*members), ageComp);
printf("Members sorted on age...\n");
for (int i = 0; i < m_count; i++) {
char *string_rep = Member_Greet(members[i]);
printf("%s\n", string_rep);
free(string_rep);
}
printf("\n");
}
Teacher, Student & Visiting Example
Teacher Student Visiting
name, birthdate, lecture name, birthdate, id_no name, birthdate, id_no,
name, age, teaches, name, age, ID_no, valid_thru
greet greet name, age, ID_no,
expired, greet

May we build an array for a collection of teachers


and students and sort its elements according to the
age or name?
May we add another type (say, Visiting) to the
existing codes?
Teacher, Student & Visiting in “C”
typedef struct { char *Member_Greet(Member member) {
char name[NAMELEN]; char *buf = (char *)malloc(BUFSIZ);
Date birthdate; char *etc = (char *)malloc(BUFSIZ/2);
category klass; sprintf(buf, "Name: %s, Age: %d",
union { member.name, Member_Age(member));
char lecture[NAMELEN]; switch (member.klass) {
int id_no; case TEACHER:
struct { sprintf(etc, ", Teaches: %s",
int id_no; member.specific.lecture);
Date valid_thru; break;
} visit_info; case STUDENT:
} specific; sprintf(etc, ", ID_no: %d",
} Member; member.specific.id_no);
break;
Member newVisiting(char *name, case VISITING:
Date birthdate, sprintf(etc,
int id_no, Date valid_thru) { ", ID_no: %d, Valid_thru: %s",
Member visiting = newMember(name, birthdate); member.specific.visit_info.id_no,
visiting.klass = VISITING; Date_String(member.specific.
visiting.specific.visit_info.id_no = id_no; visit_info.valid_thru));
visiting.specific.visit_info. break;
valid_thru = valid_thru; }
return visiting; strcat(buf, etc);
} free(etc);
return buf;
}
Teacher, Student & Visiting (Cont’d)
Teacher Student Visiting
name, birthdate, lecture name, birthdate, id_no name, birthdate, id_no,
name, age, teaches, name, age, ID_no, valid_thru
greet greet name, age, ID_no,
expired, greet

May we build an array for a collection of teachers


and students and sort its elements according to the
age or name?
May we add another type (say, Visiting) without
ever breaking existing codes?
That’s where OOP comes into play!
From ADTs to Objects
Can we define new types in terms of existing ones?
 Allow new types to inherit common parts – inheritance
Can we treat hierarchically structured types as
compatible ones?
 Allow variables of more general types (supertypes) to take
objects(values) of less general types (subtypes) – polymorphism
Can we redefine operations(methods) while keeping
the interface (message) intact?
 Allow objects to find the most related operation for the given
request at run-time – dynamic or late binding
All these traits lead to a programming style called
Object-Oriented Programming (OOP)
 Allow software systems to be more easily extended without
breaking existing code base!
Terms are Deceitful
Conventional Terms Object-Orientation Terms
(Abstract) Data Type Class
Data (Value) Object (Instance)
Data Creation Instantiation
Initialization Constructor call
Field Instance Variable
Member
Procedure Method
Procedure Call Message Passing
Data Abstraction Object-Orientation
Teacher, Student & Visiting (again)

Member
name, birthdate
name, age, greet

Teacher Student
lecture id_no
teaches, greet ID_no, greet

Visiting
valid_thru
expired, greet
Object-Oriented Languages
Simula 67
Smalltalk
Oberon-2
C++ (C syntax, Simula 67 spirit)
Java (C++ syntax, Smalltalk spirit)
C#
Objective-C (C + Smalltalk)
Python
Ruby
Go (Resurrected Oberon-2)

Teacher, Student & Visiting in “C++”
class Member { class Teacher: public Member {
public: public:
string Name(); Teacher(string name, Date birthdate,
int Age(); string teaches);
virtual string Greet(); String Teaches();
protected: string Greet();
Member(string name, Date birthdate); private:
private: string lecture;
string name; };
Date birthdate; Teacher::Teacher(string name, Date birthdate,
}; string teaches): Member(name, birthdate) {
Member::Member(string name, this->lecture = teaches;
Date birthdate) { }
this->name = name; string Teacher::Teaches() {
this->birthdate = birthdate; return this->lecture;
} }
string Member::Name() {
return this->name; string Teacher::Greet() {
} return Member::Greet() + ", Teaches: " +
int Member::Age() { this->Teaches();
return Now().GetYear() – }
this->birthdate.GetYear();
} class Student: public Member {…}
string Member::Greet() {
return "Name: " + Name() + ", Age: " + class Visiting: public Student {…}
std::to_string(Age());
}
Teacher, Student & Visiting in “C++”
bool ageComp(Member *m1, Member *m2) {
return m1->Age() < m2->Age();
}
int main(int argc, char *argv[]) {
list<Member*> members;
members.push_back(new Teacher(…));
members.push_back(new Student(…));
members.push_back(new Visiting(…));
members.sort(ageComp);
cout << "Members sorted on age..." << endl;
for (it = members.begin(); it != members.end(); ++it)
cout << ((Member *)(*it))->Greet() << endl;
cout << endl;
return 0;
}
Rethinking Teacher, Student & Visiting
IMember
name, age, greet

Member
name, birthdate
name, age, greet

Teacher Student
lecture id_no
teaches, greet ID_no, greet

Visiting
valid_thru
expired, greet
Teacher, Student & Visiting in “Java”
interface IMember { class Teacher extends Member {
public String name(); public Teacher(String name,
public int age(); LocalDate birthdate,
public String greet(); String teaches) {
} super(name, birthdate);
this.lecture = teaches;
class Member implements IMember { }
protected Member(String name, public string teaches() {
LocalDate birthdate) { return this.lecture;
this.name = name; }
this.birthdate = birthdate;
} public String greet() {
return super.greet() +
public final String name() { ", Salary: " + salary();
return this.name; }
}
private String lecture;
public final int age() { }
return LocalDate.now().getYear() -
birthdate.getYear(); class Student extends Member {…}
}
public String greet() { class Visiting extends Student {…}
return "Name: " + this.name() +
", Age: " + this.age();
}
private String name;
private LocalDate birthdate;
}
Teacher, Student & Visiting in “Java”
class AgeSorter implements Comparator<IMember> {
public int compare(IMember m1, IMember m2) {
return m1.age() - m2.age();
}
}

public class Main {


public static void main(String[] args) {
AbstractList<IMember> members = new LinkedList<IMember>();
members.add(new Teacher(…));
members.add(new Student(…));
members.add(new Visiting(…));
Collections.sort(members, new AgeSorter());
System.out.println("Members sorted on age...");
for (IMember member: members) System.out.println(member.greet());
System.out.println();
}
}
Teacher, Student & Visiting in “C#”
interface interface IMember { class Student: Member {
string Name { get; } // Property public Student(string name, DateTime birthdate,
int Age { get; } int id_no): base(name, birthdate) {
string Greet(); this.id_no = id_no;
} }
public int ID_no {
class Member: IMember { get { return id_no; }
protected Member(string name, }
DateTime birthdate) { public override string Greet() {
this.name = name; return base.Greet() + ", ID_no: " + ID_no;
this.birthdate = birthdate; }
}
public string Name { private int id_no;
get { return this.name; } }
} class Visiting: Student {
public int Age { …
get { public override string Greet() {
return DateTime.Now.Year – return base.Greet() + ", Valid thru " +
birthdate.Year; valid_thru.ToString("yyyy-MM-dd");
} }
}
public virtual string Greet() { private DateTime valid_thru;
return "Name: " + this.Name + }
", Age: " + this.Age; class Teacher: Member {…}
}
private string name;
private DateTime birthdate;
}
Teacher, Student & Visiting in “ObjC”
@interface Member: NSObject { @interface Teacher: Member {
char *name; char *lecture;
Date birthdate; }
} - (id) name: (char *) n birthdate: (Date) d
- (id) name: (char *) n teaches: (char *) t;
birthdate: (Date) d; - (char *) teaches;
- (char *) name; - (char *) greet;
- (int) age; @end
- (char *) greet;
@end
@implementation Teacher
@implementation Member - (id) name: (char *) n birthdate: (Date) d
- (id) name: (char *) n teaches: (char *) t {
birthdate: (Date) b { [super name: n birthdate: d];
name = n; lecture = teaches;
birthdate = b;
return self; return self;
} }
- (char *) teaches { return lecture; }
- (char *) name { return name; } - (char *) greet {
- (int) age; { char *buf = (char *)malloc(BUFSIZ);
return Now().year - birthdate.year; char *etc = (char *)malloc(BUFSIZ/4);
} strcpy(buf, [super greet]);
- (char *) greet { sprintf(etc, ", Teaches: %s", [self teaches]);
char *buf = (char *)malloc(BUFSIZ); strcat(buf, etc);
sprintf(buf, "Name: %s, Age: %d", free(etc);
[self name], [self age]); return buf;
return buf; }
} @end
@end
Teacher, Student & Visiting in “ObjC”
int ageComp(const void *e1, const void *e2) {
id m1 = *((id*)e1);
id m2 = *((id*)e2);
return [m1 age] - [m2 age];
}
int main(int argc, char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id members[10];
int m_count = 0;
members[m_count++] = [[[Teacher alloc] init]
name: "MH"
birthdate: newDate(1971, 12, 7)
teaches: "Programming Languages"];
members[m_count++] = [[[Student alloc] init] …];

int i;
printf("A few CAU members...\n");
for (i = 0; i < m_count; i++) {
char *string_rep = [members[i] greet];
printf("%s\n", string_rep);
free(string_rep);
}
printf("\n");
qsort(members, m_count, sizeof(members[0]), ageComp);
printf("Members sorted on age...\n");
for (i = 0; i < m_count; i++) {
char *string_rep = [members[i] greet];
printf("%s\n", string_rep);
free(string_rep);
}
[pool drain]
}
Teacher, Student & Visiting in “Python”
class Member(object):
def __init__(self, name, birthdate):
self._name = name
self._birthdate = birthdate
def name(self):
return self._name
def age(self):
# Naive and buggy
return date.today().year – self.birthdate.year
def greet(self):
return "Name: {}, Age: {}".format(self.name(), self.age())
class Teacher(Member):
def __init__(self, name, birthdate, teaches):
super().__init__(name, birthdate)
self._lecture = teaches
def teaches(self):
return self._lecture
def greet(self):
return super().greet() + ", Teaches: {}".format(self.teaches())
class Student(Member):

class Visiting(Student):

Teacher, Student & Visiting in “Ruby”
module Member class Student
def initialize(name, birthdate) include Member
@name = name def initialize(name, birthdate, id_no)
@birthdate = birthdate super(name, birthdate)
end @id_no = id_no
def name() end
return @name def ID_no()
end return @id_no
def age() end
return Date.today.year – @birthdate.year def greet()
end return super() + ", ID_no: #{ID_no()}"
def greet() end
return "Name: #{name()}, Age: #{age()}" end
end
end class Visiting < Student
def initialize(name, birthdate, id_no,
class Teacher valid_thru)
include Member # Mixin, not an inheritance super(name, birthdate, id_no)
def initialize(name, birthdate, teaches) @valid_thru = valid_thru
super(name, birthdate) end
@lecture = teaches def greet()
end return super() +
def teaches() ", Valid thru #{@valid_thru}"
return @lecture end
end
def greet() def expired()
return super() + ", Teaches: #{teaches()}" today = Date.today
end return today > @valid_thru
end end
end
One More Twist
Teacher Student Visiting
name, birthdate, lecture name, birthdate, id_no name, birthdate, id_no,
name, age, teaches, name, age, ID_no, valid_thru
greet greet name, age, ID_no,
expired, greet

May we build an array for a collection of teachers


and students and sort its elements according to the
age or name?
May we add another type (say, Visiting) without
ever breaking existing codes?
May we redefine the “age” member of class Visiting
to return 0 hiding her real age for privacy’s sake
without ever breaking existing codes?
Criticism on Class and Inheritance
Inheritance creates interdependencies
among classes that complicate maintenance
 Modifying higher level classes often breaks the
whole system. It is sometimes impossible because
it requires source codes
 Yo-yo problem caused by complicated inheritance
graph and dynamic binding
Graphic Objects Example
Graphic
location, color
location,
change_location,
color, change_color,
draw, erase

Line Circle
extent radius
extent, change_extent, radius, change_radius,
length, draw draw

FilledCircle
draw

Why didn’t we redefine erase at lower levels in the


hierarchy?
Yo-Yo Problem is Not Uncommon…
class Graphic: # A test
def erase(self): g = FilledCircle(radius=100)
print("Graphic.erase") g.erase()
self.change_color(BG_COLOR)
self.draw() Attempting erase...
# location, color, Graphic.erase
# change_location, change_color Graphic.change_color Background
class Line(Graphic): Graphic.location
def draw(self): … Circle.radius
# extend, change_extent, length FilledCircle.draw (0, 0) with radius 100
class Circle(Graphic):
def draw(self): …
# radius, change_radius
class FilledCircle(Circle):
def draw(self):
print("FilledCircle.draw", self.location(),
"with radius", self.radius())
Less Classes or Class-less OOP
Should we limit class hierarchy and dynamic
binding to the minimum?
 Keep the inheritance hierarchy as shallow as possible
Some even argued that “class” is not essential (if
not harmful) for OOP at all: Class-less OOP
 Go: duck typing, JavaScript: prototype
Teacher, Student & Visiting in “Go”
type Member struct { type Student struct {
name string Member
birthdate time.Time id_no int
} }
func (m Member) Name() string { func (s Student) ID_no() int {
return m.name return s.id_no
} }
func (m Member) Age() int { func (s Student) Greet() string {
return time.Now().Year() – return s.Member.Greet() +
m.birthdate.Year() fmt.Sprintf(", ID_no: %d", s.ID_no())
} }
func (m Member) Greet() string {
return fmt.Sprintf("Name: %s, Age: %d", type Visiting struct {
m.Name(), m.Age()) Student
} valid_thru time.Time
}
type Teacher struct { func (v Visiting) Expired() bool {
Member return time.Now().After(v.valid_thru)
lecture string }
} func (v Visiting) Greet() string {
func (t Teacher) Teaches() string { return v.Student.Greet() +
return t.lecture fmt.Sprintf(", Valid thru %s",
} format_date(v.valid_thru))
func (t Teacher) Greet() string { }
return t.Member.Greet() +
fmt.Sprintf(", Teaches: %s", t.Teaches())
}
Teacher, Student & Visiting in “Go”
type IMember interface {
Name() string
Age() int
Greet() string
}
type AgeSorter []IMember
func (m AgeSorter) Len() int { return len(m) }
func (m AgeSorter) Less(i, j int) bool { return m[i].Age() < m[j].Age() }
func (m AgeSorter) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func main() {
members := []IMember{
Teacher{Member{…}, …},
Student{Member{…}, …},
Visiting{Student{Member{…}, …}, …},
}
sort.Sort(AgeSorter(members))
fmt.Println("Members sorted on age...")
for _, member := range(members) { fmt.Println(member.Greet()) }
}
Go’s Duck Typing
type PetDog struct {}

func (p PetDog) Name() string {


return "Yeppie"
}
func (p PetDog) Age() int {
return 1 // Forever young...
}
func (p PetDog) Master() string { return "Master" }
func (p PetDog) Greet() string { return “I Dunno. Bow Wow!" }

Is PetDog a kind of IMember?


 Go says Yes – It speaks the same language as IMember
 Java says No. It does so even for Member, Teacher, Student & Visiting
Teacher, Student & Visiting in “JavaScript”
var MemberProto = {
Name: function() { return this.name; },
Age: function() { return new Date().getFullYear() - this.birthdate.getFullYear(); },
Greet: function() { return "Name: " + this.Name() + ", Age: " + this.Age(); },
__proto__: {}
};
var Member = function(name, birthdate) {
member = {};
member.name = name;
member.birthdate = birthdate;
member.__proto__ = MemberProto;
return member;
};
var TeacherProto = {
Teaches: function() { return this.lecture; },
Greet: function() {
return MemberProto.Greet.call(this) + ", Teaches: " + this.Teaches();
},
__proto__: MemberProto
};
var Teacher = function(name, birthdate, teaches) {
teacher = Member(name, birthdate);
teacher.lecture = teaches;
teacher.__proto__ = TeacherProto;
return teacher;
};
Retrospect
OO is not a mere combination of class, inheritance,
dynamic binding
 It does mean an attempt to allow extension of software
systems without breaking or requiring existing code base
 OOP has proved to foster software reuse on a grander
scale, say, hierarchical class libraries or framework libraries
Not all OO languages were born equal
 Each language has its own strengths and weaknesses
 You will never ever be allowed to settle down on single
language be it OO or not
Final Thoughts
Languages themselves do not guarantee good
programming styles
 You can write super ugly codes even in C++, Java, Python, Go,…
 Most C programs are source compatible with C++, thus using
C++ does not mean you’re doing OOP correctly
You need to use right tools for the given problems
 All the languages mentioned so far stemmed from one single
style, so called von Neumann-style
 Procedural, imperative (and object-orientation as an extension)
Beyond von Neumann languages
 Functional Programming
 Logic Programming (& Constraints Programming)
 Multi-paradigm or Polyglot Programming

Das könnte Ihnen auch gefallen