COS 333: Chapter 12, Part 1
Summary
TLDRThis lecture delves into object-oriented programming (OOP), exploring its support in high-level languages and its foundational concepts. It discusses the necessity of abstract data types, inheritance, and polymorphism in OOP languages. The talk highlights design issues like object exclusivity, subtype considerations, and inheritance models, contrasting single and multiple inheritance. It also examines dynamic binding, type checking, and the initialization of objects. The lecture provides insights into programming languages like Smalltalk, which pioneered OOP, and languages like Java and C++ that primarily support OOP but retain imperative structures.
Takeaways
- 📚 The lecture introduces Chapter 12, focusing on support for Object-Oriented Programming (OOP) in high-level languages, with a second part to follow in the last lecture of the course.
- 🔑 OOP is supported in various languages to different extents, with some being purely OOP like Smalltalk, while others like Ada and C++ offer OOP as an additional feature on top of procedural programming.
- 💡 The core concepts of OOP include abstract data types, inheritance, and polymorphism, which are essential for any language claiming to support OOP.
- 👶 Inheritance allows for the creation of new classes based on existing ones, promoting code reuse and establishing a hierarchy among classes.
- 📈 The advantages of inheritance include increased productivity through code reuse and the ability to logically structure classes in a hierarchical order.
- 🔍 Design issues in OOP languages involve considerations of object exclusivity, subtypes, type checking, single vs. multiple inheritance, object allocation, binding types, nested classes, and object initialization.
- 🔄 Dynamic binding in OOP is facilitated by polymorphic references and occurs at runtime, allowing for method calls to be bound to the correct method dynamically.
- 🚫 Abstract methods and classes are part of OOP, with abstract methods defining a protocol without an implementation and abstract classes being unable to be instantiated.
- 🔍 The script discusses three approaches to object exclusivity: treating everything as an object (as in Smalltalk), adding objects to a complete typing system (as in C++), and using an imperative typing system for primitives while making everything else an object (as in Java).
- 🤔 The disadvantages of OOP include increased complexity due to interdependencies among classes, which can complicate maintenance and upgrades.
- 📝 Smalltalk is highlighted as the first purely OOP language, with all computation handled through message passing and all objects allocated on the heap, but suffers from performance issues due to its uniform object handling and reliance on a garbage collector.
Q & A
What is the main focus of the lecture?
-The lecture primarily focuses on the support for object-oriented programming in high-level programming languages, covering the foundational concepts, design issues, and examples of programming languages that support these principles.
What are the key concepts that must be supported in an object-oriented programming language?
-An object-oriented programming language must support abstract data types, inheritance, and polymorphism.
What is the significance of inheritance in object-oriented programming?
-Inheritance allows new classes to be defined in terms of existing classes, promoting code reuse and enabling a hierarchical organization of classes.
Can you explain the difference between a class and an object in object-oriented programming?
-A class is a blueprint for creating objects, defining the properties and methods that objects of that class will have. An object is an instance of a class, representing a specific entity with its own state and behavior.
What is the meaning of polymorphism in the context of object-oriented programming?
-Polymorphism in object-oriented programming refers to the ability of different objects to respond to the same message (method call) in different ways, typically achieved through method overriding.
How does the Smalltalk programming language exemplify object-oriented programming?
-Smalltalk is considered a pure object-oriented programming language because it treats everything as an object, including primitive types like integers and floats, and it was the first language to be developed with these principles.
What are the different extents to which programming languages can support object-oriented programming?
-Programming languages can range from having very basic support for object-oriented programming as an optional feature, to being primarily object-oriented with some imperative structures, to being pure object-oriented languages that rely entirely on an object model for functionality.
What are some of the design issues that need to be considered when supporting object-oriented programming in a high-level programming language?
-Design issues include the exclusivity of objects, the consideration of subclasses as subtypes, type checking with reference to polymorphism, support for single or multiple inheritance, object allocation and de-allocation, dynamic and static binding, nested classes, and object initialization.
Why might a programming language choose to implement single inheritance over multiple inheritance?
-Single inheritance can be chosen to simplify the language and avoid complexities such as naming collisions and additional runtime overhead associated with multiple inheritance.
What is the role of abstract methods and abstract classes in object-oriented programming languages?
-Abstract methods define a protocol for a method without an implementation, ensuring that derived classes must provide their own implementation. Abstract classes cannot be instantiated and include at least one abstract method, enforcing that certain functionality is implemented by derived classes.
How does Smalltalk handle object allocation and memory management?
-In Smalltalk, all objects are allocated on the heap, and memory management is handled implicitly by a garbage collector, which frees up memory occupied by objects that are no longer in use.
What is the impact of dynamic binding on the performance of an object-oriented program?
-Dynamic binding can impact performance because the determination of which method to call is made at runtime, consuming runtime resources. However, it allows for greater flexibility and extensibility in software development.
Outlines
📘 Introduction to Object-Oriented Programming Support
This paragraph introduces the lecture's focus on the support for object-oriented programming (OOP) in high-level languages, outlining the topics to be covered, including an introduction to OOP, its concepts, and design issues. It highlights the range of OOP support in various languages, from purely procedural to purely object-oriented, with examples like Smalltalk as the first OOP language and others like Java and C# that blend OOP with imperative features.
🔑 Key Concepts of Object-Oriented Programming
The paragraph delves into the foundational concepts of OOP, emphasizing the necessity of support for abstract data types, inheritance, and polymorphism in an OOP language. Inheritance is discussed as a means to increase productivity through code reuse and to create logical hierarchies of classes. The paragraph also introduces terminology such as classes, objects, derived classes, parent classes, methods, and message passing, illustrating how these concepts contribute to the structure and behavior of OOP.
📚 Inheritance and Method Overriding in OOP
This section explores the intricacies of inheritance, including access controls and method overriding. It explains how subclasses can specialize parent classes by adding functionality and how access to class members can be restricted. The paragraph also discusses the ability of a subclass to override inherited methods, adapting their behavior to the subclass's needs, and the implications of this on the overall design of OOP languages.
🔍 Dynamic Binding and Polymorphism
The concept of dynamic binding is introduced, explaining how it allows for the determination of the correct method to call at runtime through polymorphic references. The paragraph discusses the advantages of dynamic binding for software system extension and maintenance, and touches on abstract methods and classes, which enforce that derived classes implement certain functionalities. It also covers the implications of dynamic binding on type checking and the potential for runtime errors due to type mismatches.
🏭 Design Issues in Object-Oriented Programming Languages
The paragraph addresses several design considerations for OOP languages, such as the reliance on objects, subtype relationships, type checking with polymorphism, support for single or multiple inheritance, object allocation and de-allocation, binding dynamics, nested classes, and object initialization. It sets the stage for a deeper discussion on how different programming languages approach these design issues and the trade-offs involved in their implementation.
🌐 Object Exclusivity and Subtype Considerations
This section examines the design issue of object exclusivity, discussing the approaches where everything is an object, versus adding objects to an existing type system, and using an imperative type system for primitives while treating everything else as an object. It also explores the implications of considering subclasses as subtypes, focusing on the 'is-a' relationship and its impact on the behavior compatibility between parent and derived classes.
🎛️ Polymorphism and Inheritance Challenges
The paragraph delves into the challenges associated with polymorphism and inheritance, particularly the complexities introduced by multiple inheritance and the concept of diamond inheritance. It discusses the potential for naming collisions and the increased cost of dynamic binding when multiple inheritance is involved, while also highlighting the flexibility and power that multiple inheritance offers in expressing complex inheritance structures.
📦 Object Allocation, De-allocation, and Binding
This section discusses the allocation and de-allocation of objects, the distinction between stack and heap allocation, and the implications of subtypes on object assignment. It also addresses the decision between dynamic and static binding for messages within an OOP language, considering the trade-offs between efficiency and flexibility, and the programmer's ability to specify binding types in languages like C++.
🛠️ Nested Classes and Object Initialization
The paragraph considers the support for nested classes, their visibility to the nesting class and vice versa, and the initialization of objects, including the use of constructors and default initialization. It explores the design decisions related to the visibility of class members and the handling of parent class member initialization in subclasses.
🔑 Smalltalk: The Pure Object-Oriented Programming Language
This final paragraph provides an overview of Smalltalk as the first purely object-oriented programming language. It discusses the language's characteristics, such as the treatment of all elements as objects, heap allocation, message passing for computation, dynamic type checking, and its simple inheritance model. The paragraph also touches on the limitations of Smalltalk, including its performance due to the uniform use of message passing and garbage collection.
Mindmap
Keywords
💡Object-Oriented Programming (OOP)
💡Inheritance
💡Polymorphism
💡Abstract Data Types (ADTs)
💡Encapsulation
💡Design Issues
💡Smalltalk
💡Dynamic Binding
💡Abstract Classes
💡Message Passing
💡Garbage Collection
Highlights
Introduction to support for object-oriented programming in higher-level languages and the topics to be covered in the lecture.
Discussion on the varying degrees of object-oriented programming support across different programming languages, from full support to basic features.
Explanation of the three core concepts of object-oriented programming: abstract data types, inheritance, and polymorphism.
The benefits of inheritance in object-oriented programming for code reuse and the creation of class hierarchies.
Introduction to object-oriented terminology such as classes, objects, derived classes, parent classes, methods, and message passing.
The role of access controls in object-oriented programming for encapsulation and the concept of protected access.
The importance of dynamic binding in object-oriented programming for method calls and its advantages for software system extension and maintenance.
The concept of abstract methods and classes in object-oriented programming and their necessity for ensuring derived class implementations.
Design issues in object-oriented programming languages, including the exclusivity of objects, subtype considerations, and type checking with polymorphism.
Different approaches to object allocation and de-allocation in object-oriented programming and their implications.
The impact of single versus multiple inheritance on object-oriented programming languages and associated complexities.
Discussion on object initialization in object-oriented programming, including constructor usage and inheritance of parent class members.
Overview of object-oriented programming support in Smalltalk, the first object-oriented programming language.
Smalltalk's unique approach to treating everything as an object, including basic types, and its implications for performance.
The use of message passing for computation in Smalltalk and its role in making the language uniform but potentially slower.
Smalltalk's handling of object allocation and garbage collection, and the potential disadvantages of relying on a garbage collector.
Dynamic type checking and its runtime implications for Smalltalk's performance and error detection.
Inheritance in Smalltalk, including the rules for method overriding and accessing overridden methods in parent classes.
Transcripts
welcome to today's lecture which deals
with the first part of chapter 12
covering support for object oriented
programming there will be a second part
which will be covered in the last
lecture for the course
these are the topics that we will be
discussing in today's lecture
we'll begin with a quick introduction
into how object-oriented programming is
supported in higher level programming
languages
we'll then move on to
the introductory concepts related to
object-oriented programming itself
and we'll look at all of the various
concepts that must be supported in an
object-oriented programming language
we'll then move on to a number of design
issues that need to be considered if one
is to support object-oriented
programming in a high-level programming
language and these design issues will be
used for the remainder of the discussion
on this chapter where we'll look at a
couple of different examples of
programming languages and how they
support object-oriented programming
principles
we'll finish this lecture off by looking
at the first of these programming
language examples
namely the small talk programming
language and small talk was the very
first object-oriented programming
language to be developed
now there are a wide variety of
different programming languages that
support object-oriented programming and
what we see in practice is a kind of a
continuum
so different programming languages
support object-oriented programming to
different extents
some programming languages have a very
full pure representation of
object-oriented programming and are
primarily object oriented whereas other
programming languages only have very
basic support for object oriented
programming
so what we see in practice is quite a
number of programming languages are
primarily procedural and data oriented
so in these programming languages we
generally speaking have support for
imperative programming structures
so things like
structs
enumerations unions and those sorts of
things but then in addition they have an
object-oriented programming model that
is kind of added on top of everything
else that the programming language
supports so for these languages
object-oriented programming is more of
an optional feature that can be used by
the programmer and languages that fall
into this category are for example ada
95 and c plus
then there are some object-oriented
programming languages that also support
functional programming
a good example of this would be class
which is the common lisp object system
and this adds object-oriented
programming support to a lisp like
dialect
newer programming languages
that are
supporting object oriented programming
may not support other paradigms at all
so they may be fairly pure
object-oriented programming languages
however they may retain some basic
imperative structures
so good examples of languages that fall
in this category are java and c-sharp
both of these languages are primarily
object oriented but they do provide
support for certain
non-object-oriented concepts for example
imperative type systems
and then a small number of programming
languages are considered to be pure
object-oriented programming languages
they rely entirely on an object model to
achieve their functionality and they
have nothing from the imperative model
included at all so in these languages
even primitive types like integers and
floats would be represented as objects
small talk being the very first
object-oriented programming language
is very much in this category and also
more recently
ruby can be considered to be a pure
object-oriented programming language
so now let's move on to what is required
for an object-oriented programming
language to be considered object
oriented in nature
so every object-oriented programming
language must support three things
firstly it must provide support for
abstract data types which we discussed
in the previous chapter
abstract data types provide a means for
encapsulating information related to an
object as well as behavior related to
that object
then an object-oriented programming
language also needs to support
inheritance which is the central theme
in object-oriented programming
and then related to inheritance
we also need support for polymorphism in
an object-oriented programming language
and polymorphism refers to the dynamic
binding of method calls to methods now
we'll look at all of these concepts as
we continue with our discussion in this
lecture
so let's begin by looking at the first
important edition
that object-oriented programming
languages bring into the mix which is
inheritance
so we know that productivity can be
increased if we can reuse parts of an
existing implementation
this is because we don't need to
re-implement these existing parts we
simply use them as they exist
now there are two problems associated
with the basic abstract data types that
we discussed in the previous chapter
firstly they are very difficult to reuse
without performing some relatively
drastic changes
in effect what you would have to do is
copy the entire adt out and then make a
series of whatever required changes are
needed
to this copied abstract data type so
this of course then doesn't allow for a
lot of reuse of existing program code
secondly all of these abstract data
types are essentially independent from
one another they are self-contained
units and they all exist at exactly the
same level
so inheritance then if it is supported
in an object-oriented programming
language allows new classes to be fi
defined in terms of existing classes so
in other words these new classes can
then inherit common parts from existing
classes so for example we might have a
person class and we might define for
this person class a name and an age for
example so in other words every person
then has their own name and age now we
may then have inherited classes from
person for example we may have a student
class and a lecturer class and maybe a
pensioner class and these would then
inherit from the person class
what this then means is that the student
lecturer and pensioner classes don't
need to implement any functionality
related to the name and age that is
defined for the person class
because they are derived classes or
children of the person class they then
already have that functionality included
so inheritance then addresses both of
the problems associated
with regular abstract data types
firstly they allow a lot of reuse
of adts after only a few minor changes
so for example if we look at a student
class it can inherit all of the
functionality from the person class
which it doesn't need to re-implement
and then all it needs to do is implement
functionality related to what is
specific for a student for example the
student's student number
and for example the
final results for all of the subjects
that the student has taken
secondly they also then allow for
classes to be defined in a hierarchy so
this means we can then logically
construct a series of classes that
relate to one another in a very natural
hierarchical fashion for example a
student is a kind of person and
therefore it logically makes sense for
students to inherit from the person adt
so now let's look at some terminology
related to object oriented programming
firstly the adts that we implement are
usually referred to as classes in an
object-oriented programming language
now instances of these classes are
usually called objects so an instance is
an actual instantiation of a class which
we can then work with and we can create
as many instances as we want of a class
now a class that inherits is referred to
as a derived class or a subclass
so in my example the student lecturer
and pensioner classes are all derived
classes or sub classes
the class from which another class
inherits is referred to as a parent
class or a super class so in my example
the parent class or super class would be
the person class
we then also have sub programs that
define operations on objects in other
words the behavior of a particular
object
and these are usually referred to as
methods in some programming languages
the term member function will be used as
well but in a purely object-oriented
sense we usually call these methods
calls to methods in an object-oriented
programming language are called messages
so when we have a number of objects that
are sending messages back and forth we
refer to this as message passing
now of course an object may have a
number of methods associated with it and
these methods all together define the
behavior that is valid for the object in
question
so the entire collection of all of the
objects methods is referred to as the
message protocol or the message
interface or sometimes just the
interface of the object
now messages have two parts firstly we
have the method name and secondly we
have the destination object so if we go
back to my previous example if we have a
student class and we create an object of
the student class which is called s
then the student class may have a method
associated with it called print
so we would call this print method then
on an object that we have created and
this object is an instance
so we would have s dot print
so in this example s would then be the
destination object that's the object
that we are sending the print message to
and print would be the method name so
this is then actually the message that
we are sending to the object
now in the simplest case a class will
inherit all of the entities from its
parent and then it can add more entities
in other words essentially the child
class or the derived class
specializes the parent clause by adding
additional appropriate functionality
inheritance can be complicated by what
are referred to as access controls that
are applied to encapsulated entities so
when we are talking about encapsulated
entities we are talking either about
member variables
or methods that exist within a class
so we can then apply access controls to
these entities
so a class could hide entities from its
subclasses a class could also hide
entities from its clients or it could do
both hiding entities from both
sub-classes and clients
it may also be possible for a class to
hide entities from its clients
while allowing its sub-classes to see
them and we would refer to this as
protected access
now strictly speaking protected access
is not necessary
however it is convenient
but strictly speaking an object-oriented
programming language only really needs
to differentiate between hiding data
from its subclasses and clients or
making it accessible to both of them
now besides inheriting methods as they
are a class can also modify an inherited
method so if we go back to my previous
example
our person class may provide a print
method and then we may re-implement this
print method in a different way in our
student class
so in this case what we would say then
is that the student class overrides the
inherited print method from its parent
class
and the method in the parent class in
other words the print method in the
person class is said to be overridden
now we mentioned in the last chapter
that adts have data associated with them
which are represented by means of member
variables that belong to the adts and
they also have some kind of behavior
associated with them which would be
implemented by means of a method or a
member function
so the same of course then is true for
classes and then also obviously objects
which are instances of classes in an
object-oriented programming language
so there are two kinds of variables that
can be associated with a class we can
firstly have a class variable
and a class variable has one instance of
that variable that exists
for the entire class so in other words
all of the objects of that class share
the class variables
and then we also have instance variables
and an instance variable has one
instance per object that is created of
that particular class
so a good example of this would be a
class that represents a savings account
savings accounts
and share an interest rate which is
common to all of these accounts so the
interest rate would be represented by
means of a class variable
however each individual
savings account has its own balance
which is separate and independent from
all other savings account objects
so the balance of a savings account
would be represented by means of an
instance variable there being one per
object of the savings account class
now to correspond with these two kinds
of variables there are also two kinds of
methods that can be associated with the
class
firstly we have class methods and these
accept messages that go to the class as
a whole
in some object oriented programming
languages it's also possible to call
class methods on objects of the class
but the point is that the message goes
to the class not to an individual object
and then we have instance methods and
these accept messages for individual
objects in other words instances of a
class
so for example in if we have our savings
accounts class from our previous example
that i've just used
then a get interest rate and set
interest rate method would be class
methods because they work with data
related to the class as a whole so those
would then be messages that would be
sent to the savings account class
an instance method in this example would
be a
get balance or set balance method these
must be sent to objects because they
work with data related to each
individual object namely the balance of
the account
now we've previously mentioned that
inheritance is also very important in
object-oriented programming languages
and there is also differentiation
between single inheritance where we have
each class only having a single parent
and multiple inheritance where a class
may have multiple parents we'll go into
detail on the difference between single
inheritance and multiple inheritance
later on
in this lecture
now object oriented programming is
obviously a very useful feature to add
to a high-level programming language but
it doesn't come without disadvantages
so
one big disadvantage associated with
inheritance
and the class system in object-oriented
programming languages is that
interdependencies are created amongst
classes and this is of course because we
have classes that inherit from parent
classes and therefore they rely on some
of the functionality in the parent class
so this may then complicate maintenance
because if we change a parent class then
it may require changes in all of the
derived classes that inherit from it
so now we've looked at the first two
requirements that an object-oriented
programming language must fulfill
firstly the presence of adts
and secondly a mechanism for inheritance
we can now move on to the third
important requirement for
object-oriented programming which is
dynamic binding
so dynamic binding happens through
what's called a polymorphic reference or
pointer
and a polymorphic reference or pointer
can refer to objects of either a class
or a descendant of that class in other
words a class that inherits from the
class in question
so here we have an example of this
we have a pointer over here called p
and this is a pointer to a person
object
so this pointer can now be used as a
polymorphic pointer and we do that by
assigning to this pointer a new student
object that has been created
so this student object is an instance of
the student class but because we assume
that the student class inherits from the
person class
we can now use this pointer p which is a
person pointer to refer to a student we
could also do the same thing if we had a
lecturer class that inherits from person
in which case we would then set p to be
a new lecturer and in fact we could do
this with any class that inherits from
the person class
now it's important to understand
that we must use a reference or a
pointer in order to create this
polymorphic structure
that we've just demonstrated it
becomes more complex when we are working
with actual objects so in other words a
person object or a student object but
we'll get to more detail on this a
little bit later on in this lecture
now when
overwritten methods are called through a
polymorphic variable then the binding to
the correct method will be dynamic in
nature in other words it will occur at
runtime
so let's say for example that our person
class includes a print method and our
student class overrides this print
method so it provides its own version of
the print method what will then happen
is if we call print on this pointer p
then we will polymorphically call the
correct version of the print method so
in other words instead of calling the
person classes print method we will call
the student classes print method but
this must occur dynamically at run time
and this is because we can only
determine what the actual type is that
is being referred to
through the p pointer at a runtime this
can't be determined at compile time
so this dynamic binding then allows for
the easy extension
of software systems during development
as well as maintenance
now related to dynamic bindings some
programming languages provide support
for abstract methods and abstract
classes in c class abstract methods are
referred to as pure virtual methods
so an abstract method then does not
include a definition instead it only
defines a protocol for that method so
there's no actual implementation of the
body for an abstract method
an abstract class then includes at least
one abstract method possibly more
and but very importantly an abstract
class cannot be instantiated so we can't
create objects of an abstract class
now abstract methods are used to ensure
that certain functionality must be
implemented by derived classes so if we
go back to our previous example of the
person and student class
and the lecturer and pensioner classes
all three of which inherit from the
person class then we might decide that
we want to ensure that every person
object can be printed however it might
not make sense for us to implement the
print method in the person class
so what we can do is we can provide an
abstract method for the print method
and that would be in the person class it
wouldn't include any implementation at
all but what this thing does is it
ensures that all of the derived classes
must implement this print method
unless they will also be abstract if we
want to create instances of the student
class the lecturer class and pensioner
class then they must all implement the
print method
that will then mean that these classes
will be concrete and we can therefore
create
instances of the student the lecturer
and the pensioner classes
we can of course create pointers
or references
to the person class and this will allow
us to still polymorphically
use that point then to
allow assigning to it of any of the
derived classes however we can't
directly create an instance of the
person class itself because it is now
abstract
so now we've discussed the basics of
object oriented programming and we can
move on to the design issues which we
will use in order to discuss the example
object-oriented programming languages
which we'll discuss towards the end of
this lecture and over the course of the
next lecture
so there are a number of design issues
related to object-oriented programming
firstly we have the exclusivity of
objects so this relates to how heavily
the programming language relies on
objects and their classes
do they rely very heavily on
objects
are objects simply added on as an
additional feature where the rest of the
programming language is imperative in
nature and what sort of balance between
those can we achieve within the
programming language
then we have a very important question
of where the subclasses are considered
to be subtypes we'll talk about that in
some more detail in a moment then we
need to consider type checking with
reference to polymorphism so this
relates to how type checking for
messages occur in other words how do we
type check methods that are called
for a particular class
then we have support for single and or
multiple inheritance so should the
programming language support only single
inheritance or should it also allow for
multiple inheritance and what kind of
problems are associated with multiple
inheritance and how can we address those
problems
next we have object allocation and
de-allocation
so this relates to whether objects can
be allocated on the stack or on the heap
and how this allocation happens and how
de-allocation of these objects will take
place is the allocation manual or does
it take place automatically
then
questions related to dynamic and static
binding are also important
so this relates again to polymorphic
messages where we call polymorphic
methods related to a particular class
through a polymorphic reference or
pointer
so
is this binding dynamic is it static or
can the programmer decide whether it's
dynamic or static in certain instances
next we have the question of nested
classes so some object-oriented
programming languages allow classes to
be nested others do not if nested
classes are allowed then what will the
semantics be related to these nested
classes
so what data can these nested classes
directly access
and what data can the containing class
access within a nested class
and then finally we have the
initialization of objects how do objects
get initialized
do they have constructors and if so are
these constructors called automatically
or do they have to be explicitly called
now we'll look at each of these design
issues separately and then we'll move on
to our programming language examples and
look at how each of the programming
languages will consider in this chapter
answer these various design issues and
deal with the various problems that are
associated with those decisions
so let's start off by looking at the
first of our design issues namely the
exclusivity of objects so as i mentioned
on the previous slide this relates to
how heavily the programming language
depends on objects and the classes that
define these objects now they're broadly
speaking three approaches that we can
use related to the exclusivity of
objects and we'll look at examples of
all three of these when we get to the
example programming languages towards
the end of this chapter
so the first approach that can be used
is that everything in the programming
language is an object now when we say
everything we mean every single possible
thing that can be represented in the
language is an object so this extends to
very basic entities things like integers
floats doubles and boolean values these
are not primitive values these are
actually objects that are represented so
an example of a programming language
that uses this approach is small talk
which is a purely object-oriented
programming language
so the big advantage associated with
this approach is that it's very elegant
and it's very uniform everything works
the same way because everything is an
object so everything works by means of
message passing
and we manipulate
objects so we are always working with
the same kinds of data entities there
are no exceptions
the bigger disadvantage however is that
simple operations are very slow and this
is because there is always some overhead
introduced whenever we are working with
objects
so objects take up a little bit more
space in memory because we need to
represent information related to how the
object is stored in memory and how its
resources are allocated also whenever we
call a method on an object then there is
some additional processing overhead that
has to take place to allow for the
message passing to happen and this is
particularly the case if we are working
with polymorphic references to objects
the second approach that we can use is
that we can add objects to a complete
typing system
so this is the case in a programming
language like c plus
here we have a language that is
primarily imperative so we have a lot of
features that the language supports
things like structs things like
enumerations things like unions but then
in addition to this we then have an
object model that is essentially built
onto the language
so the big advantage with this is that
simple operations can be very fast
because they are represented in a very
primitive fashion we can for example
work with unions and as we know unions
are very memory efficient and they will
also be efficient from an operational
perspective because we're not working
with objects in that case
however the big disadvantage to this
approach is that it creates a very
confusing type system we now not only
have to worry about objects and their
classes we also have to worry about all
of these other entities that don't
follow the object model
the third approach that we can use is
something of a middle ground between the
other two approaches so here we use an
imperative typing system for primitives
but then we make everything else an
object
java is an example of a programming
language that uses this approach so in
java primitive types like ins floats
doubles and boolean values are all
represented as primitives but then
everything else is represented using
objects
so the advantage here then is that
simple operations involving these
primitive types can be very fast but the
typing system still remains very small
and manageable so we only have to deal
with a small set of primitive types and
then objects and there are no additional
types such as unions for instance or
structs or anything else that would
complicate the system
the disadvantage however is that we are
still dealing with two type systems that
we have to use together however this
problem is not as bad as a situation
where we have an entire imperative type
system
with an object model attached to it
so what i would like you to do at this
point is to pause the video and try to
think how each of these three approaches
compare in terms of orthogonality
the next design issue that needs to be
answered for an object-oriented
programming language
is are subclasses considered to be
subtypes
so this boils down to the question of
whether an is a relationship holds
between a subclass object and a parent
class object
so if we take this back to my previous
example where we have a person class in
the student class
if we can say that a student
is a type of person then an is a
relationship holds between them
and in this case we would then say that
the derived class the student class is a
subtype of the parent class in other
words the person class
so even is a relationship holds between
a subclass object and a parent class
object then objects of the derived class
must behave in the same way as the
parent class object
so in other words whatever behavior is
associated with the parent class
in terms of messages that the parent
class can respond to that same behavior
must be implemented in the derived
clause
so as i said then the derived clause is
considered to be a subtype if this is a
relationship holds
[Music]
but
subclasses then in this case are
somewhat limited so subclasses can only
add variables and methods
to the variables and methods that are
inherited from the parent class it is
not possible for the subclass to remove
variables or methods if variables or
methods are removed by the derived
clause then this means that the derived
clause no longer behaves in exactly the
same way as the parent class did so
we're only allowed to add additional
functionality in the derived clause
also if the derived clause overrides
methods that are provided in the parent
class then this overriding must happen
in a compatible way
so the overridden methods must have the
same number of parameters as the method
that they are overriding and also the
parameters and return types must be type
compatible with one another some
programming languages limit this even
further and require that the parameters
and return types of the overridden
methods must be exactly the same as the
methods in the parent class that are
being overridden
the next design issue that we need to
consider is how type checking works in
the presence of polymorphism
so if our object-oriented programming
language is to be strongly typed then we
need to check two things whenever a
polymorphic message is sent to a method
through a polymorphic pointer or
reference
these two things are firstly that the
formal parameters of the method
match the parameter types of the message
that is being sent to the object
and then secondly that the return type
of the method matches the expected
return type of the message sent to the
object
now this type checking can occur
dynamically at runtime however the two
major drawbacks associated with this
firstly it's relatively costly and this
is because the type checking has to
happen at runtime and therefore it
consumes runtime resources because it
isn't taking place prior to runtime
during compilation
secondly error detection is delayed
until run time so this means that we
won't necessarily pick up type
mismatches when we compile a program
instead we will detect these mismatches
at runtime as the program is executing
now we can make this type checking
static however we then need to introduce
an additional restriction
to our object-oriented programming
language and this is that the overriding
methods must be restricted to have
exactly the same parameter and return
types as the parents method that is
being overridden
this then ensures that there won't be
any difference between the method that
is actually being called and the one
that is present in the parent class and
therefore checking is easy and can
happen at compile time because the types
are all
ensured to be correct
the next design issue that we need to
consider is whether an object-oriented
programming language will support only
single inheritance or multiple
inheritance
so multiple inheritance quite simply is
a situation where a newly defined class
inherits from two or more parent
classes now the advantage associated
with support for multiple inheritance is
that it gives us some additional
flexibility and power
it allows us to conveniently express
fairly complicated inheritance
structures and can be fairly useful in
certain situations
however multiple inheritance does have
two drawbacks associated with it the
biggest drawback is that it adds
complexity to the language itself
as well as some implementation
complexity for a programmer who's using
multiple inheritance
now this primarily relates to collisions
between
names
so this happens in a situation where we
have two parent classes that have
entities with the same name
so let's say for example that we have a
class called c
and it inherits from two parent classes
p1 and p2
now if p1 and p2 both implement a print
method then this means that we have two
print methods that are inherited by the
derived class c
and in this situation it's up to the
programmer typically to specifically
indicate which of the parent classes
they are referring to when the print
method is called in the derived class c
now these kinds of naming collisions are
implicit when diamond inheritance occurs
and we'll look at diamond inheritance in
some more detail on the next slide
the second disadvantage associated with
multiple inheritance is that there's an
additional level of inefficiency that is
introduced to it
and this is because dynamic binding
costs a little bit more whenever
multiple inheritance is involved the
reason for this is that if a method is
called in a derived class and it is not
defined within that derived class then
multiple parents have to be searched for
the implementation of that method that
is being called and that obviously takes
more time during execution
however this inefficiency is not a major
inefficiency and therefore this
disadvantage is not a great one
so here we have a diagram illustrating
diamond inheritance
we have a situation where we have a
single derived clause called a in this
case
and a inherits from two parents
b
on that side and c on the other side
b and c then both inherit from the same
parent which is class a right at the top
of the diamond
so what's important to understand with
diamond inheritance
is that the problem doesn't depend on
what is implemented in either class b
or class c
instead let's assume that we have a
method implemented in class a
and this method is a print method
so what this means then is that b will
inherit the print method from a and c
will also inherit the same print method
from a now at this point class a has two
parents b and c
and both of them have a print method
present
now it doesn't matter that these print
methods are exactly the same because
they've been inherited from the same
parent class a in this example the point
is that they are two distinct print
methods even though the implementation
is exactly the same and therefore when
class a refers to the print method it
can't be sure whether we are referring
to the one in class b or class c
so typically in class a we then need to
use some kind of scope resolution to
indicate that we are referring to the
print method either in class a or class
b or class c
that will then alleviate the problem
because we've indicated to the compiler
specifically which method we are
referring to
a number of issues need to be considered
when we are looking at our next design
issue which relates to the allocation
and de-allocation of objects so this all
relates to where objects are allocated
from and where they are deallocated and
this of course then might be either the
stack or the heap or a combination of
these
so if objects in an object oriented
programming language behave like adts
then it means that we can allocate them
from the runtime stack if we simply
declare a variable that has the type of
a particular class
or alternatively we can explicitly
create them on the heap
typically what would happen here is that
we would have to use an explicit
operator like new in order to allocate
the object on the heap
now it is possible that an
object-oriented programming language may
have all of its objects allocated on the
heap
and in this case then all of these
objects that are used in this
object-oriented programming language
will be used through either pointers or
reference variables now this is the case
in java every object is handled by means
of a reference
so this vastly simplifies assignment
because seeing as we're not working with
stack allocated objects we don't have to
perform a copy from one object to
another instead we are simply assigning
references or pointers to each other so
we are just been performing a reference
copy
now dereferencing can be implicit within
an object-oriented programming language
and again this is the case in java we
don't explicitly have to de-reference
our references to objects we simply use
those references and it is as though we
are using the objects that are being
referred to
now if objects are allowed to be stack
dynamic then then an additional
complexity comes into play and this
occurs when we are working with subtypes
so let's assume that we have two classes
a and b
and we assume that b inherits from a and
b is also a subtype of a so this means
all of the operations then that are
valid for a are also valid for b
so now let's consider this program code
over here so we have a variable called
avar which is of type a what's important
to understand here is that avar
is stack allocated so it is not
allocated on the heap it's allocated on
the runtime stack
then we have another variable bivar
which is of type b that's also legal and
now we perform an assignment where we
are assigning b far to ava now this is
legal because as we've already seen a
moment ago b is a subclass of a
now if we assume that class b adds
additional variables in other words it's
storing additional data
in addition to the data that is defined
for class a
and what happens here is a truncation or
sometimes this is referred to as object
slicing
so what happens here is because ava and
bivar have been allocated on the stack
ava only has space for whatever
variables are defined for class a
b var has also those variables defined
for class a but additionally it has some
more variables that have been defined
but
there is no space for those additional
variables in ava so what happens then is
only the variables that are
valid for ava in other words defined
within class a are copied from a beaver
so this is a partial copy that takes
place and part of the data is then lost
during this assignment
the last question that we need to answer
which falls into this category
is if we have heap allocated objects
then is heap allocation explicit or
implicit
so in some object-oriented programming
languages like c plus we need to
explicitly de-allocate heap allocated
objects using delete
in other programming languages this
isn't required so for example in small
talk and in java we have the garbage
collector which automatically implicitly
takes care of cleaning up heap allocated
objects for us
the next design issue that needs to be
considered is whether dynamic and static
binding can occur for messages within an
object-oriented programming language
and if so then how are they dealt with
now
should every binding then be dynamic in
nature well obviously it's not an option
for none of the bindings to be dynamic
because in that case we can't have
dynamic message binding and this is one
of the cornerstones that is very central
to object oriented programming
so we may decide to make all of our
bindings be dynamic
however this is very inefficient because
all of the bindings will then happen at
runtime and therefore will consume
runtime resources
what i would like you to do at this
point is to pause the video and try to
see if you can think of any advantages
to making all of our method bindings
dynamic in nature
a middle ground thing between these two
approaches is that we could allow the
programmer to specify which bindings are
static and which are dynamic this is the
route that c plus provides for us
and what i would like you to do at this
point is again pause the video and see
if you can think of any advantages and
disadvantages to this approach
the second last design issue we need to
consider in an object-oriented
programming language is whether nested
classes will be supported or not
so if a new class is defined and it's
needed only by one other class then
there's no reason for this new class to
be visible to any other classes
so an object-oriented programming
language may decide to allow for the new
class to be nested inside the class that
uses it
a good example of this would be a linked
list class
a linked list is built up out of nodes
but it is not necessary for anything
outside of the linked list class to know
about these nodes
all that external classes or functions
are interested in would be the data that
is contained within the linked list so a
programming language may allow the node
class to be nested inside the linked
list class
an object oriented programming language
may go even further than this and it may
allow a new class to be nested inside a
sub-program
now there are
two main issues that need to be
considered even is that classes are
supported and these both relate to the
visibility of members within a class
so firstly we need to consider
the visibility of members within the
nesting class and how they are visible
to the nested class
and secondly we need to consider how
members of the nested class are visible
to the nesting class so some programming
languages may allow for complete access
to all of the members even private
members
some programming languages may restrict
this access somehow and we'll look at
some of these examples in the
programming language examples we get to
later on in this discussion
the final design issue relates to how
objects are initialized so this relates
to the creation of objects
so firstly an object-oriented
programming language needs to decide if
objects are initialized to values when
they are created so in other words we're
talking about the initialization of the
member variables of a class
now the initialization might be explicit
in which case we would actually
explicitly call a constructor
or the initialization may be implicit
initialization would be implicit in a
situation where a programming language
provides a default constructor that is
implicitly provided and doesn't have to
be implemented by the programmer in that
case when an object is created then this
default constructor would be
automatically called
we also then need to consider how parent
class members are initialized when a
sub-class object is created and this is
a little bit more interesting than the
initialization of data that is
specifically defined for a class
so again here we may have explicit
initialization or implicit
initialization
with implicit initialization we would
have a situation where the parent
classes default constructor would be
automatically called
when the derived classes constructor is
called
with explicit initialization we would
always need to explicitly indicate which
constructor in the parent class we want
to invoke when a constructor in the
child class
is initiated
we will now move on to the last topic of
this lectures discussion where we will
look at object-oriented programming
support in the small talk programming
language
so small talk was the very first
object-oriented programming language and
it is considered to be a purely
object-oriented programming language for
a very long time it was in fact the only
purely object-oriented programming
language
so as such small talk is the basis for
most object-oriented programming
concepts in other programming languages
as we use them today
now in small talk everything is an
object so this includes all of the very
basic types like integers and floats
this means that small talk has no
characteristics of imperative
programming languages at all and all of
its objects are allocated from the heap
so there are no stack allocated objects
in small talk
now the fact that everything is an
object in small talk makes the language
very slow so what i would like you to do
at this point is to pause the video and
try to explain why this is the case
now in small talk all computation is
also handled in a uniform fashion
and this is by means of message passing
between objects
so all of the operations that are
performed in small talk are before
performed in a standard uniform fashion
now this also is another factor that
makes small talk relatively slow and
what i would like you to do at this
point is to again pause the video and
try to explain why this is the case
now because all objects in small talk
are heap allocated they need to be
accessed either by means of a pointer or
by a reference
in the case of small talk object access
happens by means of typeless reference
variables
so
there is no need to work with pointers
and references are also implicitly
de-referenced so there is no need to use
complex dereferencing notation in order
to access objects instead objects are
simply referred to by name
now all the allocation of objects takes
place implicitly and this is because
small talk uses a garbage collector to
free up memory that is occupied by
objects that are no longer required
now this the allocation can be slow
depending on how the garbage collector
is implemented
in whichever version of small talk is
being used
what i would like you to do at this
point is to pause the video and see if
you can think of another disadvantage
of this reliance on a garbage collector
that small talk has
small talk of course implements
polymorphism and therefore there has to
be type checking for messages that are
sent to objects
so all bindings of messages to methods
in small talk takes place dynamically at
run time and the procedure that is used
to find a matching method is quite
simple it's a search process that is
performed and the search starts in the
object to which the message has been
sent
if a matching method is not found in
this object then we move on to the
parent of the object that the message
has been seen to and perform a search
there the search continues up the
hierarchy until eventually the object
class is reached the object class is the
single class that is at the root of all
classes in small talk
now if a match is not found by the stage
that the object class has been reached
then this means that the method has not
been found and therefore a type mismatch
occurs
so type checking then as a result can
only occur at run time as well and is
therefore dynamic in nature
so as i said a type error occurs when no
matching method is found through this
search process
and as a result of this type errors can
then only be detected at runtime
so this runtime type checking is also
another factor that makes more talk slow
because once again the checking
procedure takes up resources at run time
finally inheritance in small talk is
also fairly simple and straightforward
so in small talk subclasses can inherit
from superclasses and a subclass will
inherit all of the instance variables
instance methods and class methods from
its superclass
now in small talk all subclasses are
subtypes so this means that subclasses
can only add to the functionality that
they inherit from their super class
um it's not possible for the subclass to
hide any functionality that appears in
the parent class
now the inheritance model in small talk
is fairly simple
methods with the same name and protocol
as a parent method override the parent
method
however it is possible for the derived
class to access an overridden method in
a parent class it does this by means of
the super special word so essentially we
just use super to refer to the parent
class and then we can access any
functionality that has been overridden
and is therefore not directly accessible
in the parent class
small talk also only supports single
inheritance and doesn't support multiple
inheritance at all
all right so that concludes this
discussion in the next lecture we will
finish off the chapter by looking at
some more examples of object-oriented
programming languages
Weitere verwandte Videos ansehen
COS 333: Chapter 12, Part 2
Features of Object Oriented Programming Part 2 | C ++ Tutorial | Mr. Kishore
OOPS Interview Questions and Answers | Object Oriented Programming Interview Questions C#
Java Basic OOP Concepts | Features of OOPs in Java | Learn Coding
La Lógica de la Programación Orientada a Objetos explicada con Minecraft
COS 333: Chapter 2, Part 3
5.0 / 5 (0 votes)