Tải bản đầy đủ (.pdf) (20 trang)

data abstraction and object orientation

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (2.57 MB, 20 trang )

<span class="text_page_counter">Trang 1</span><div class="page_container" data-page="1">

VNU UNIVERSITY OF SCIENCE

REPORT

Data abstraction and object orientation

Lectures : <sub>Nguy n Th Minh Huy n </sub><b><sub>ễ</sub><sub>ị</sub><sub>ề</sub></b>Students : <b>Dương</b> Quang Kh i 21001556 <b>ả –</b>

: <b>Tô Quốc Thái Dương – 21000514 </b>

: <b>Đoàn ữ</b> H u Hoan 21000517 <b>–</b>

Class : MAT3541E 3-4

</div><span class="text_page_counter">Trang 2</span><div class="page_container" data-page="2">

3. Fire Safety in Agricultural Structures/Farms ...Error! Bookmark not defined.

3.1. Artificial-Intelligence-Based Networks for Fire

Prevention/Monitoring/Simulation ... Error! Bookmark not defined.3.2. The gradient descent (GD) algorithm operates as follows: ... Error! Bookmark not defined.

3.3. Future Prospects of AI in Agricultural Structures and Beyond . Error! Bookmark not defined.

4. Image fire detection algorithms based on convolutional neural networks (CNN) ... Error! Bookmark not defined.

4.1. Introduction ... Error! Bookmark not defined.4.2. The proposed framework ... Error! Bookmark not defined.4.3. Image object detection networks comparison ... Error! Bookmark not defined.

</div><span class="text_page_counter">Trang 3</span><div class="page_container" data-page="3">

1. Object-oriented programming

Object-oriented programming aims to enhance the possibilities for reusing code by providing a convenient way to create new abstractions as extensions or improvements of existing ones. In order to illustrate this concept, let's consider a collection of integers implemented as a doubly linked list of records (for other types of objects, please refer to Section 1.1). In Figure 1, you can find the C++ code for the elements in our collection. This example follows a "module-astype" style of abstraction, where each element is a distinct object belonging to the class list_node. The class includes both data members (prev, next, head_node, and val) and subroutine members (predecessor, successor, insert_before, and remove). In many object-oriented languages, subroutine members are referred to as methods, while data members are known as fields. In C++, the keyword "this" refers to the object that the currently executing method belongs to. In Smalltalk and Objective-C, the equivalent keyword is "self," and in Eiffel, it is "current."

Given the existence of the list_node class, we could define a list of integers as follows:

Figure 1 A simple class for list nodes in C++. In this example we envision a list of integers To create an empty list, one could then write:

</div><span class="text_page_counter">Trang 4</span><div class="page_container" data-page="4">

Records to be inserted into a list are created in much the same way:

In C++, one can also simply declare an object of a given class:

Our list class contains a field called "header" as an object. When the object is created using the "new" keyword, it is allocated in the heap. However, when it is created through a declaration, it is allocated either statically or on the stack, depending on its lifetime. Regardless of whether they are on the stack or in the heap, the creation of an object triggers

</div><span class="text_page_counter">Trang 5</span><div class="page_container" data-page="5">

the execution of a constructor, which is a programmer-specified initialization routine. In languages like C++, Java, and C#, the constructor has the same name as the class itself. In C++, there is also an option to define a destructor method, which is automatically invoked when an object is destroyed. The destructor's name is the same as the class name, but with a leading tilde (~). Destructors are commonly used for managing storage and performing error checking.

If a constructor includes parameters, it is necessary to provide the corresponding arguments when declaring an object in-line or creating an object on the heap. For instance, let's consider the scenario where our list_node constructor was designed to require an explicit parameter:

Each in-line declaration or call to new would then need to provide a value:

Public and Private Members

The declaration of the list_node includes a public label which distinguishes the members required for implementing the abstraction from the members accessible to users of the abstraction. Members that come after the public label are accessible outside the class, while members that come before are not. In C++, it is also possible to use a private label, allowing the public portions to be listed first if desired. Unlike some other programming languages, C++ classes have public data and methods that are automatically accessible by default, without the need for individual labeling. Additionally, certain implementation details can be omitted from the initial C++ class declaration and placed separately, making them invisible to users of the abstraction.

</div><span class="text_page_counter">Trang 6</span><div class="page_container" data-page="6">

DESIGN & IMPLEMENTATION What goes in a class declaration?

The declaration of the class should encompass all the essential details that are required for utilizing and compiling the abstraction. Initially, it should consist of the necessary information to ensure proper usage. Additionally, it needs to fulfill the requirements of the compiler in order to generate the code effectively. This often results in the inclusion of additional private information into the interface, particularly in languages that follow the value model and necessitate instance sizes. Furthermore, declarations tend to incorporate method bodies that are essential for the compiler when it comes to inlining performance-critical small methods.

Tiny Subroutines

Object-oriented programs use more, shorter subroutines than imperative ones since direct field access gets wrapped in object methods. Public fields breach encapsulation by exposing internals, preventing internal changes without user code changes too. The list_node val field arguably should thus be private, with get/set methods instead.

Derived Classes

Derived classes in object-oriented programming allow creating specialized versions of existing classes through inheritance. A derived class inherits the data fields and methods of its base class and can add new fields and methods.

The key aspects of derived classes are: Specialization, Reuse, Extensibility, Transitivity, Encapsulation, Polymorphism

In summary, derived classes are fundamental to object-oriented programming and support specialization and extensibility of classes through inheritance and polymorphism. Careful design of class hierarchies with derived classes is key to flexible and reusable code. Objects as Fields of Other Objects

As an alternative to deriving queue from list, we might choose to include a list as a field of a queue instead:

</div><span class="text_page_counter">Trang 7</span><div class="page_container" data-page="7">

Inheritance is best when a derived class object (client) can fill a base class (person) context, behaving specially due to its derived nature (printing extra info). Here queue's relation to list is small: we either view queue as a special list, or queue as using list internally. Compelling inheritance enables polymorphism: derived instances used polymorphically via base class interfaces

1.1. Classes and Generics

Our lists and queues assume integer node items. Dynamically typed languages naturally enable lists/queues of any object by leaving val untyped. Statically typed languages like C++ might use subclasses typed per value, but this has issues. Generally, templates enable reusable data structures for any type without subclassing in C++.

DESIGN & IMPLEMENTATION Containers/collections

Containers like sets, stacks, queues hold class objects, implemented via data structures. Key container library design issues are: inheritance hierarchies, operations and time complexity, memory allocation/garbage collection, type safety, generics, and iteration. Building safe, efficient, flexible containers is complex. With many considerations - like using templates for type safety instead of casts - excellent library design is difficult but critical.

2. Encapsulation and Inheritance

Encapsulation involves grouping together data and associated operations, while concealing the specifics of how it is implemented. Object-oriented programming can be seen as an expansion of modular programming, which emphasizes the separation of interface and implementation. When inheritance is introduced, it introduces additional considerations for hiding data and controlling visibility. Certain programming languages incorporate inheritance into static record modules, allowing the benefits of data hiding to be separate from objects. However, dynamic polymorphism in object-oriented programming typically requires dynamic dispatch, thereby connecting encapsulation and objects.

2.1. Modules

Early modular languages like Clu and Euclid grouped module declaration and definition. Modula-2 allowed separate header/body files but no public/private header parts: everything exported. Limited data hiding used pointers hiding internal structs. Ada added more flexibility, letting package headers separate public and private sections for selective exporting.

</div><span class="text_page_counter">Trang 8</span><div class="page_container" data-page="8">

The section dedicated to private modules contains important information needed by the compiler for memory allocation. Modifying this section may necessitate recompilation by the user, but it does not require any changes to the source code. On the other hand, alterations made to the public section can lead to changes in user code, as they modify the interface. Static modules do not present any special concerns regarding code generation - internal data is managed in the same way as external data. When it comes to module types, their implementation can resemble records, with sections of fixed or variable size and a descriptor. This descriptor can be placed statically, on the stack, or on the heap, depending on the requirements.

<b>The “this” Parameter </b>

Modules can contain shared subroutines, but how do they access instance data? Copying instance wastes space. Instead, subroutines take the instance address as an extra "self" argument. This pointer provides instance-specific data access without replication.

per-A Euclid call of the form is translated as if it were really

where my_stack is passed by reference. The same translation occurs in objectoriented languages.

Making Do without Module Headers

In contrast to C/C++ headers and bodies, Java/C# modules merge interface and implementation. There is no need to divide the code into public and private sections because the compiler automatically extracts public information. While a basic outline of code can be helpful for project management, fully developed implementations enable automatic extraction of interfaces, making the development process more efficient.

2.2. Classes

Inheritance needs additional visibility rules beyond modules. Key issues: should private base members be visible to derived methods? Should public base members always stay public to derived users? Example: queue privately derives list, hiding its public members from queue users, except empty - re-exposed via using. C++ allows the inverse strategy as well: methods of an otherwise public base class can be explicitly deleted from the derived class:

In addition to public and private visibility, C++ allows the protected keyword to make members visible only to class methods or derived classes. The basic philosophy is:

- A class limits member visibility - public members are visible when class scope is active, private only in class methods, protected in methods of the class/descendants. - Derived classes can restrict base class member visibility but not increase it. - A derived class can restore base class member visibility with a using declaration.

</div><span class="text_page_counter">Trang 9</span><div class="page_container" data-page="9">

Other languages differ:

- Eiffel allows flexible control over visibility, including in derived classes. - Java lacks base class protect/private and protects package-visible members. - C# adds assembly-wide internal visibility.

- Smalltalk/Objective-C allow attempting to call any method at runtime.

So C++ protected offers class or descendant visibility, with other aspects like derived class control and language differences worth noting.

Static Fields and Methods

Orthogonal to visibility, most OO languages allow declaring static class members "belonging" to the whole class, not instances. Called class fields/methods, one copy exists shared across instances - changes are visible to all objects. Static methods lack a this parameter so can't access instance fields, while instance methods can access both static and instance fields. Static members model class-wide rather than per-instance state.

2.3. Nesting (Inner Classes)

Nested classes raise visibility questions: can inners access outers, and which instance? C++/C# allow only static outer access, since static has one instance, serving only to hide. Java enables full outer access by associating each inner instance with an outer instance. So design options exist: hide via nesting, access static outers, or access instance outers.

In Java, each inner instance is linked to an outer instance, allowing for access. The inner instance has a concealed reference to its outer instance. Therefore, when there are multiple instances of the outer class, each call to Inner.bar() will access the appropriate value of 'n' based on its association with the outer instance. Static nesting restricts access to static outer instances, similar to C++ or C#. Local classes have the additional capability of accessing method parameters and variables, which must be effectively final in order to allow for copying rather than referencing the surrounding frame. Both inner and local classes are widely used for closures and anonymous handlers through the use of the 'new' keyword.

</div><span class="text_page_counter">Trang 10</span><div class="page_container" data-page="10">

2.4. Type Extensions

Several languages have added object-oriented features like inheritance and dynamic dispatch to existing modular languages with encapsulation, through a mechanism called type extensions. These include Modula-3, Oberon, CLOS, Ada 95/2005, and Fortran 2003. Rather than alter the existing module system, these languages allow extending record types to create derived types that inherit fields and behaviors. Ada 2005 demonstrates this through tagged types that enable building class hierarchies. A child package like the queue extending the list package resembles a derived class, inheriting list's implementation. But the child package remains a module, retaining encapsulation separately from the inheritance mechanism.

So while languages like Smalltalk were designed from the ground up for objects, other languages have increased support for object-oriented programming by adding type extensions. This allows inheritance reuse while preserving existing modular abstraction capabilities. The combination enables flexible object-oriented code while avoiding disruption to legacy systems.

2.5. Extending without Inheritance

Inheritance extends existing abstractions, but isn't always possible - a class may forbid it via final in Java or sealed in C#. Even when allowed, changing variable types from an existing base class name to a new derived name across a large legacy codebase may be infeasible. So while a core motivation for and strength of OOP, inheritance has limitations. When unavailable or impractical, an alternative called composition creates complex objects by aggregating others.

</div>

×