ЩЕ РАЗ ПРО ОБ’ЄКТИ І ОБ’ЄКТНИХ КЛАСАХ

У цій главі певні поняття, представлені в попередньому розділі, описані більш докладно Розглянемо більш складний приклад з двома обєктними класами: DEPT (Відділ) і ОМР (Співробітник) Припустимо, що в системі вже були описані визначені користувачем класи MONEY (Гроші) і JOB (Робота), а клас CHAR (Символьна змінна) є вбудованим Тоді операції, необхідні для створення класів DEPT і ОМР, можуть виглядати наступним чином (з використанням деякого гіпотетичного синтаксису)

5 Рассматриваемыеобъектыобязательнодолжныбытьизменяемыми(объясните,почему)

CLASS DEPT

PUBLIC ( DEPT#                                                                                                                        CHAR, DNAME                                                                                                                        CHAR, BUDGET                                                                                     MONEY, MGR                                                                                  OID ( EMP ) ,

EMPSOID ( SET ( OID ( EMP ) ) ) )

METHODS ( HIRE_EMP( OID ( EMP ) ) <Код> ,

FIRE_EMP( OID ( EMP ) ) <Код> , .. ) ..

CLASS EMP

PUBLIC ( EMP#                                                                                                                         CHAR, ENAME                                                                                                                         CHAR, SALARY                                                                                     MONEY, POSITION                                          OID ( JOB ) )

METHODS ( .. ) ..                                                                                     

Необхідно відзначити кілька наведених нижче важливих особливостей

1 У цьому прикладі опис відділів і співробітників побудовано на основі ієрархії вкладення, у якій обєкти ОМР концептуально містяться всередині обєктів DEPT Таким чином, обєкт класу DEPT містить відкриту змінну ек земпляров MGR, що представляє керівника відділу, а також змінну EMPS, що представляє співробітників відділу Точніше, обєкти класу DEPT містять від криту змінну примірника MGR, значення якої є покажчиком (тобто ідентифікатором) обєкта співробітника, і змінну EMPS, значення якої є покажчиком на безліч покажчиків на співробітників Поняття ієрархії вкладення в ширшій формі буде представлено нижче

2 У даному прикладі в обєкти класу ОМР НЕ була включена деяка змінна екземпляра, що містить ідентифікатор обєкта відділу DEPT, або ж значення номера відділу DEPT # (змінна екземпляра для зовнішнього ключа) Це рішення узгоджується з обраним нами методом подання звязки між відділами та співробітниками за допомогою ієрархії вкладення Але це також означає, що ні су ществует можливості прямого переходу від заданого обєкта класу ОМР до ​​соот відповідне йому обєкту класу DEPT Детальніше дане питання обговорюється в підрозділі Звязки розділу 255

3 Зверніть увагу на те, що визначення кожного класу містить оголошення методів, які застосовуються до обєктів цього класу (без включення про граммного коду) Цільовими класами для подібних методів є, безуслов але, класи, визначення яких включають визначення даного метода6

На рис 254 наведено кілька прикладів екземплярів обєктів для визначених раніше класів DEPT і ОМР Розглянемо обєкт ОМР, показаний у верхній частині малюнка (з ідентифікатором (OID) еее), який містить перераховані нижче компоненти

6 Відзначимо, що в нашому гіпотетичному синтаксисі змішуються поняття моделі та реалізації (хоча така ситуація і небажана, але дуже типова) Крім того, автор в іншій роботі ([1412]) довів, що приклад з відділами та співробітниками все одно погано підходить для вивчення обєктних класів Однак дане питання ми тут обговорювати не будемо, оскільки довелося б занадто далеко відійти від основної теми

■ Незмінний обєкт Е001 вбудованого класу CHAR у відкритій змінної примірника ОМР #

■ Незмінний обєкт Smith вбудованого класу CHAR у відкритій змінної примірника ENAME

■ Незмінний обєкт $ 50 000 певного користувачем класу MONEY у відкритій змінної примірника SALARY

■&nbsp&nbsp&nbsp&nbsp Ідентифікатор (OID) змінюваного обекта7 певного користувачем класу

JOB у відкритій змінної примірника POSITION

Рис 254 Приклад екземплярів обєктів класів DEPT і ОМР

Обєкт ОМР також включає принаймні дві додаткові закриті змінні екземпляра, одна з яких (OID) містить ідентифікатор еее самого обєкта ОМР, а інша (CLASS) – ідентифікатор, що визначає клас обєкта (Class-Defining Object – CDO) для обєктів співробітників ОМР, що дозволяє знайти код методів даного обєкта

Примітка Ці два ідентифікатора фізично можуть зберігатися як разом з обєктом, так і окремо від нього Наприклад, значення еее не обовязково має зберігатися як частина відповідного обєкта ОМР необхідно тільки, щоб в додатку був

заданий певний спосіб виявлення обєкта ОМР за даним значенням еее (тобто, щоб

було задано деяке відображення величини еее на фізичну адресу обєкта ОМР)

Однак концептуально користувач завжди може вважати ідентифікатор обєкта частиною цього обєкта

Тепер розглянемо обєкт DEPT, розташований в центрі малюнка, з ідентифікатором (OID) ddd, який містить перераховані нижче обєкти

■ Незмінний обєкт D01 вбудованого класу CHAR у відкритій змінної примірника DEPT #

■ Незмінний обєкт Mktg вбудованого класу CHAR у відкритій змінної примірника DNAME

■ Незмінний обєкт $ 1 000 000 певного користувачем класу

MONEY у відкритій змінної примірника BUDGET

■ Ідентифікатор еее змінюваного обєкта певного користувачем класу ОМР у відкритій змінної примірника MGR (це ідентифікатор обєкта, що представляє керівника відділу)

■ Ідентифікатор sss змінюваного обєкта певного користувачем класу

SET (OID (ОМР)) у відкритій змінної примірника EMPS

■ Дві закриті змінні екземпляра, що містять ідентифікатор (OID) ddd                                                                                    самого обєкта DEPT та ідентифікатор відповідного обєкта, що визначає клас

Обєкт з ідентифікатором sss складається з набору ідентифікаторів індивідуальних

(Змінюваних) обєктів класу ОМР, а також звичайних закритих змінних екземпляра

На рис 254 екземпляри обєктів представлені в тому вигляді, в якому вони реально існують, тобто на малюнку відображається компонент структури даних обєктної моделі, що дозволяє чіткіше уявити саму обєктну модель Зазвичай в книгах або документації такі схеми не використовуються замість цього дані представляються так, як на рис 255, на більш високому рівні абстракції, що, як прийнято вважати, полегшує розуміння обєктної моделі

Наведена на рис 255 схема більшою мірою узгоджується з інтерпретацією на основі ієрархії вкладення Проте в ній залишається прихованим той важливий факт (як уже було сказано), що в обєктах часто містяться не власними інші обєкти як такі, а скоріше ідентифікатори цих інших обєктів (тобто покажчики на ці обєкти) Наприклад, згідно рис 255 можна припустити, що обєкт класу DEPT для відділу з номером D01 містить два примірника обєкта класу ОМР для співробітника з номером Е001 (при цьому, крім усього іншого, може відбутися так, що співробітник з номером Е001 отримує дві різні зарплати) Така ситуація може призвести до плутанини, тому перевагу слід віддавати схемам, подібним наведеної на рис 254

На додаток до цього слід зазначити, що реальні визначення обєктних класів сприяють виникненню заплутаних ситуацій, оскільки змінні екземпляра

в них зазвичай визначаються не як ідентифікатори OID (як у наведених вище виразах з використанням гіпотетичного синтаксису), а на основі безпосереднього відображення ієрархії вкладення Тому, наприклад, змінні екземпляра

EMPS в обєктних класі DEPT зазвичай визначаються не як OID (SET (OID (ОМР))), а в більш короткій формі: SET (ОМР) Незважаючи на деяку громіздкість повного запису, ми все ж вважаємо за краще наш стиль, як більш ясний і точний

Слід зазначити, що вся колишня критика ієрархічного підходу (наприклад, ієрархії вкладення, втіленої в СУБД IMS) в основному ставилася саме до ієрархіям вкладення Детальний розгляд даного питання зайняло б занадто багато місця, тому досить сказати, що основним аргументом такої критики було відсутність симетрії Зокрема, ієрархії не зовсім зручні для представлення відносин типу багато до багатьох. Наприклад, для розглянутого раніше відносини постачальників і деталей може виникнути питання, містяться Чи обєкти-постачальники в обектахдеталях або навпаки А може, вірно і те й інше А що можна сказати про відносини постачальників, деталей і проектів

Рис 255 Приклад подання екземплярів обєктів DEPT і ОМР у відповідності з ієрархією їх вкладення

Дійсно, подібних запитань більше, ніж можна було б припустити З одного боку, як ми переконалися, обєкти являють собою ієрархію, і до них також відносяться звичні критичні зауваження щодо ієрархій А з іншого боку, як виявляється з рис 254, такі обєкти насправді образ не ієрархію, а кортежі з перерахованими нижче компонентами

1 Незмінні подобекти, тобто самоідентіфіціруемие значення, такі як це ліе числа і грошові суми

2 Ідентифікатори змінюваних подобектов, тобто покажчики на інші (можливо,

спільно використовувані) змінювані обєкти

3 Безлічі, списки, масиви і тд обєктів, перелічених у пп 1, 2 і в цьому пункті

До цього списку слід також додати певні приховані компоненти Особливої ​​уваги заслуговує п 3, оскільки зазвичай обєктні системи підтримують кілька генераторів типу колекцій (SET, LIST, ARRAY та ін), але зазвичай не підтримують тип RELATION (відношення) Такі генератори можуть використовуватися в як завгодно складних поєднаннях Наприклад, в певних обставинах як один обєкт може розглядатися масив списків мультимножин масивів покажчиків на цілочисельні змінні Додаткові відомості з цієї теми наведені в підрозділі Порівняння понять класів, примірників і колекцій нижче в даному розділі

Ще раз про ідентифікатор обєкта

Щоб послатися на обєкт або ідентифікувати його, в сучасних реляційних СУБД зазвичай використовуються ключі, які визначаються і керовані користувачами (далі для стислості будемо називати їх користувацькими ключами) (Хоча як було описано в розділах 1 і 3, в реляційних базах даних покажчики на зразок ідентифікаторів обєктів фактично навмисно заборонені див також продовження цієї теми у главі 26) Але добре відомо, що застосування користувальницьких ключів повязане з деякими проблемами Ці проблеми досить детально розглядаються в [1411] і [1421], де зроблено висновок, що реляційні СУБД, принаймні, в якості альтернативи повинні підтримувати і ключі, що визначаються системою {сурогатні) Доводи на користь ідентифікаторів обєктів в обєктних системах подібні доводам на користь сурогатних ключів в реляційних системах (Проте їх не слід прирівнювати один до одного, оскільки сурогатні ключі – Це доступні користувачеві звичайні значення, а ідентифікатори обєктів – це адреси, які, принаймні, концептуально, від користувача приховані В [2517] широко обговорюється це розходження та інші повязані з ним питання)

З цього випливають деякі наведені нижче важливі висновки

1 Необхідно розуміти, що, як буде показано в розділі 254, наявність идентифи Катор обєктів не дозволяє повністю виключити застосування користувач ських ключів Точніше, для користувача ключі необхідні для спілкування із зовнішнім світом, хоча всередині бази даних всі обєкти можуть посилатися один на інший тільки за допомогою ідентифікаторів обєктів

2 Що є ідентифікатором похідного обєкта, наприклад зєднання неко торого обєкта класу ОМР І відповідного обєкта класу DEPT або проекції обєкту класу DEPT ПО атрибутам BUDGET І MGR ЦЕ дуже важливе питання для похідних обєктів, розгляд якого ми відкладемо до розділу 255

3 Ідентифікатори обєктів часто служать предметом критичних зауважень, ви кликаних тим, що обєктні системи виглядають, як модифікований стан дарт CODASYL . Як було описано в розділі 1, стандарт CODASYL використовував ся для мережевих систем управління базами даних (наприклад для СУБД IDMS), які були створені до появи реляційного підходу Використання ідентифікаторів обєктів призводить до низкорівневому стилю программиро вання (див розділ 254), що дуже нагадує застарілий стиль програмування ня, заснований на використанні покажчиків, відповідно до стандарту CODASYL

Крім того, оскільки ідентифікатори обєктів є покажчиками, часто можна зустріти наступні твердження

По-перше, системи типу CODASYL ближче до обєктним системам, ніж реляційні

■ По-друге, реляційні системи засновані на значеннях, в той час як обєк проектні системи – на ідентифікаторах

Порівняння понять класів, примірників і колекцій

В області обєктних систем чітко розділяються концепції класу, примірника і колекції Як вже зазначалося, клас є по суті типом даних, причому він може бути вбудованим або певним користувачем, а також може бути як завгодно сложним8 Кожен клас здатний прийняти повідомлення NEW, яке призводить до створення нового (змінюваного) примірника обєкта даного класу викликається цим повідомленням метод називають конструктором класу Нижче наводиться приклад такого повідомлення, записаного за допомогою деякого гіпотетичного синтаксису

Е: = EMP NEW (E001, Smith, MONEY (50000), POS)

Тут програмна змінна POS містить ідентифікатор деякого обєкту класу JOB, а метод NEW викликається для створення нового екземпляра класу ОМР в результаті такого виклику створюється новий обєкт даного класу, відбувається ініціалізації змінних екземпляра заданими значеннями і повертається ідентифікатор нового обєкта Потім цей ідентифікатор присвоюється програмної змінної Е

Оскільки одні обєкти можуть посилатися на будь-які інші обєкти за допомогою ідентифікаторів, один обєкт може спільно використовуватися декількома іншими обєктами Зокрема, один і той же обєкт може одночасно ставитися до декількох різних колекціям обєктів У продовження розглянутого прикладу наведемо ще одне наступний вираз

CLASS EMP_COLL

PUBLIC ( EMPS OID ( SET ( OID ( EMP ) ) ) ) ..; ALL_EMPS := EMP_COLL NEW (

) ALL_EMPS ADD ( E )

Пояснення

■ Обєкт класу EMP_COLL містить одну відкриту змінну примірника EMPS, значенням якої є покажчик (ідентифікатор) на змінюваний обєкт, значення якого представляє собою безліч покажчиків (ідентифікаторів) на окремі обєкти класу ОМР

■ ALL_EMPS – це програмна змінна, значенням якої є иденти фікатор обєкта класу EMP_COLL Після виконання операції присвоювання

8 Як вже було сказано в розділі 252, в деяких системах використовуються обидва поняття – і тип, і клас. У цих системах тип означає тип поняття, тобто йогозміст або сутність, а клас означає застосування цього поняття, тобто певну колекцію, або інодіреалізацію(Розглянутого типу) В інших системах дані терміни використовуються інакше .. Ми ж як і раніше будемо вживати для позначення типу термін клас, в тому ж сенсі, що і в главі 5

вона міститиме ідентифікатор обєкта, значенням якого, в свою чергу,

буде ідентифікатор порожнього безлічі ідентифікаторів обєктів ОМР

■ ADD – це метод обєктів класу EMP_COLL У розглянутому прикладі даний метод застосовується до обєкта класу, ідентифікатор якого міститься в програмній змінної ALL_EMPS, І призначається для додавання ідентифікатора обєкта ОМР, який міститься в програмній змінної Е, до безлічі ідентифікаторів (спочатку пустому) Причому ідентифікатор цього обєкта міститься в обєкті EMP_COLL, ідентифікатор якого знаходиться в програмній змінної ALL_EMPS

Розглянувши наведену вище послідовність операцій, можна помітити, що змінна ALL_EMPS позначає колекцію обєктів ОМР, яка в даний час містить тільки один обєкт, а саме – обєкт ОМР, що описує співробітника з номером Е001 Крім усього іншого, зверніть увагу на те, що необхідно згадати значення користувальницького ключа в останньому реченні

Безумовно, в деякий заданий момент може існувати будь-яку кількість різних і, можливо, перекриваються множин обєктів співробітників, наприклад, як показано нижче

PROGRAMMERS := EMP_COLL NEW ( )

; PROGRAMMERS ADD ( E )

HIGHLY_PAID := EMP_COLL NEW ( )

; HIGHLY_PAID ADD ( E )

Наведений нижче приклад вираження SQL показує, що в реляційних системах все організовано зовсім по-іншому

CREATE TABLE ОМР

(ОМР # .. NOT NULL,

ENAME   ..    NOT NULL , SALARY  ..    NOT NULL , POSITION ..    NOT NULL ) ..

У цьому випадку за допомогою оператора SQL одночасно створюютьсяітип,і колекція, причому складний тип відповідає заголовку таблиці, а початково порожня колекція відповідає тілу таблиці Точно так же наведене нижче вираз SQL дозволяє одночасно і створити окремий рядок ОМР, і додати її до колекції ОМР (для спрощення передбачається, що цей оператор INSERT дійсно вставляє тільки єдиний рядок)

INSERT INTO ОМР (..) VALUES (..)

Можна зробити висновок, що організація цих дій за допомогою мови SQL характеризується наведеними нижче особливостями

1 Відсутня можливість забезпечити існування окремого обєкта ОМР без включення його до складу деякої колекції при цьому фактично є тільки одна і тільки одна така колекція (Але необхідно також враховувати зауваження, наведені нижче, і звернути увагу на те, що рядок ОМР не повною мірою можна вважати обєктом, як показано в главі 26)

2 Не існує безпосереднього способу створення двох різних колекцій

обєктів ОМР одного і того ж класу (Подробиці наведені нижче)

3 Не існує безпосереднього способу спільного використання одного і того ж обєкта в декількох колекціях обєктів ОМР (подробиці наведені нижче)

Іноді можна почути саме такі зауваження, однак вони не витримують серйозної критики По-перше, для досягнення аналогічного ефекту в кожному випадку може застосовуватися реляційний метод використання зовнішнього ключа Наприклад, можна визначити дві базові таблиці, PROGRAMMERS (Програмісти) і HIGHLY_PAID (Високооплачувані), кожна з яких складається з номерів відповідних співробітників По-друге, що ще важливіше, для досягнення того ж ефекту може бути застосований реляційний метод з використаннямуявлень Наприклад, таблиці PROGRAMMERS і HIGHLY_PAID можна визначити як такі уявлення, створені на основі базової таблиці ОМР

CREATE VIEW PROGRAMMERS

AS SELECT EMP#, ENAME, SALARY, POSITION FROM   EMP WHERE POSITION = Programmer

CREATE VIEW HIGHLY_PAID

AS SELECT EMP#, ENAME, SALARY, POSITION FROM EMP WHERE SALARY &gt деяке граничне значення

Тепер один і той ж обєкт ОМР можна цілком розмістити одночасно в двох або декількох колекціях Крім того, приналежність до цих колекціям, які є уявленнями, контролюється системою автоматично, а не програмістом вручну

Завершуючи цю тему, слід згадати про одну цікаву паралелі, що існує між змінюваними обєктами обєктних систем і явно заданими динамічними зміннимидеяких мов програмування (наприклад, змінними типу

BASED мови PL / I) Як і у випадку змінюваних обєктів даного класу, може існувати будь-яку кількість окремих явних динамічних змінних даного типу, память для яких виділяється під час виконання в результаті явно визначаються в програмі дій Більш того, ці окремі змінні, як і окремі змінні обєкти, не мають імен, тому на них необхідно посилатися за допомогою покажчиків Наприклад, у мові PL/I можна записати таку послідовність виразів

DCL XYZ INTEGER BASED / * XYZ змінна типу BASED * / DCL P POINTER , / * Р – мінлива-покажчик                                                                                                                                                                                               */

ALLOCATE XYZ SET (Р) / * Створити новий екземпляр XYZ, * /

/ * І привласнити змінної Р значення, яке

*/

/ * Вказує на цей екземпляр*/

Р -> XYZ = 3 / * Привласнити значення 3 екземпляру  */

/ * XYZ, на який вказує Р * /

Цей записаний мовою PL/I код дуже схожий на розглянутий раніше обєктний код Зокрема, оголошення змінної типу BASED подібно створенню класу обєктів, а застосування операції ALLOCATE – створенню нового екземпляра обєкта цього

класу за допомогою повідомлення NEW Таким чином, основна причина, по якій в обєктній моделі необхідні ідентифікатори, полягає в тому, що ті обєкти, які вони ідентифікують, не володіють унікальними іменами (точно так само, як екземпляри змінних типу BASED в мові PL / I)

Ієрархії класів

Опис основних концепцій обєктного підходу було б неповним без розгляду ієрархій класів (Їх не слід плутати з ієрархіями вкладення) Однак обєктна концепція ієрархії класів, по суті, є аналогічною концепції ієрархії типів, яка детально розглядалася в розділі 20 Отже, тут можна обмежитися декількома короткими визначеннями (здебільшого це – перефразовані визначення з глави 20) і відповідними висновками

Примітка Нагадаємо, що в обєктних світі, як і в інших випадках, все ще немає повної узгодженості щодо концепції абстрактної моделі успадкування, тому різні системи успадкування істотно відрізняються одна від іншої на більш низькому рівні деталізації

Почнемо з того, що обєктний клас Y називається подклассом класу X, а обєктний клас X – суперкласом обєктного класу у тоді і тільки тоді, коли кожен обєкт

класу Y обовязково є також обєктом класу X (Тобто у ISA X ) У цьому випадку обєкт класу у наследует9 змінні екземпляра і методи класу х Спадкування змінних екземпляра зазвичай називають спадкуванням структури, а спадкування методів – спадкуванням поведінки У істинно обєктних системах не може бути спадкування структури, а можливо лише спадкування поведінки (принаймні, це стосується скалярів або повністю інкапсульованих обєктів), оскільки відсутня структура, яка може бути успадкована (під цим мається на увазі структура, доступна

користувачеві) Але на практиці обєктні системи зазвичай не є такими чистими і в якійсь мірі підтримують успадкування структури, яке, підкреслюємо, означає спадкування відкритих змінних екземпляра

Примітка Якщо підклас містить додаткові відкриті змінні екземпляра, крім тих, які він успадковує від (безпосередньо попередньому йому) суперкласу, то прийнято застосовувати вираз, що цей підклас розширює свій суперклас

Якщо клас У є підкласом класу X, то користувачеві надається можливість застосовувати обєкт класу У замість обєкта класу X скрізь, де це припустимо, тобто в якості фактичного параметра різних методів Цей принцип називається

принципом заменяемости і вельми корисний для повторного використання коду Однак, оскільки в обєктних системах не завжди чітко простежується різниця між значеннями і змінними (тобто між незмінними і

змінюваними обєктами), виникають складнощі при проведенні відмінностей між заменяемости значень і змінних (це питання додатково обговорюється в главі 20) Засіб, що дозволяє застосовувати один і той же метод

для обєктів класу х і класу у, називається поліморфізмом

9 Він, мабуть, успадкує також закриті змінні екземпляра, але автор розглядає таке спадкування як проблему реалізації, а не як складову частину моделі

Зазвичай в обєктних системах заздалегідь передбачені певні вбудовані ієрархії класів Наприклад, в системі OPAL (див розділ 254) кожен клас розглядається як підклас деякого рівня вбудованого класу OBJECT (оскільки все є обєктами) Вбудовані підкласи класу OBJECT включають класи BOOLEAN, CHAR, INTEGER, COLLECTION та ін Клас COLLECTION в свою чергу включає підклас BAG, а клас BAG містить клас SET І ТД І ТП (АЛЕ, мабуть, COLLECTION, BAG і SET не є класами як такими, а генераторами класів на зразок RELATION в мові Tutorial D Створюється враження, що в цьому питанні є деяка плутанина)

Ще одне важливе зауваження полягає в тому, що обєктні системи зазвичай не допускають зміни класу обєкта (див анотацію до [2012]) Внаслідок цього обєктні системи не підтримують уточнення або узагальнення за допомогою обмежень, тому

такі системи не здатні підтримувати те, що, на думку автора, можна вважати

“Якісної моделлю успадкування Ця тема розкрита більш детально в наступному розділі (у розділі 263)

Нарешті, в деяких системах, крім одиночного наслідування, в тій чи іншій формі підтримується множиннеспадкування Але авторові не відомо жодної

системи, яка підтримувала б спадкування кортежів або відносин (як одиночне, так і множинне) в тому сенсі, який вказаний в [33]

Джерело: Дейт К Дж, Введення в системи баз даних, 8-е видання: Пер з англ – М: Видавничий дім «Вільямс», 2005 – 1328 с: Ил – Парал тит англ

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*