М
И Н И СТ Е РСТ В О О Б РА ЗО В А Н И Я И Н А У К И
Ф
ИВ АНО КАФ
РО
ССИ Й СК О Й
Ф
Е Д Е РА Ц И И
Е Д Е РА Л Ь ...
98 downloads
168 Views
709KB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
М
И Н И СТ Е РСТ В О О Б РА ЗО В А Н И Я И Н А У К И
Ф
ИВ АНО КАФ
РО
ССИ Й СК О Й
Ф
Е Д Е РА Ц И И
Е Д Е РА Л Ь Н О Е А Г Е Н Т СТ В О ПО О Б РА ЗО В А Н И Ю В СК И Й Г О СУ Д А РСТ В Е Н Н Ы Й У Н И В Е РСИ Т Е Т
Е Д РА В Ы ЧИ СЛ И Т Е Л Ь Н О Й И ПРИ К Л А Д Н О Й М А Т Е М А Т И К И
В В Е Д Е Н И Е В О Б ЪЕ К Т Н О -О РИ Е Н Т И РО В А Н Н О Е ПРО Г РА М М И РО В А Н И Е Н А Я ЗЫ К Е OBJECT PASCAL
М етодические указания к курсукомп ь ю терны х наук
И в анов о И з д ат ел ь с т в о«И в анов с кий гос уд арс т в енны й унив ерс ит ет » 2005
С оста вител ь: с т арш ий препод ав ат ел ь кафед ры в ы чис л ит ел ь ной и прикл ад ной м ат ем ат ики Е . В . Со ко лов
Рас с м ат рив ают с я ос нов ны е понят ия объект но-ориент иров анного програм м иров ания и егореал из ация в яз ы ке Object Pascal, яв л яющем с я час т ь ю с ред ы раз работ ки Borland Delphi. Пред наз начает с я с т уд ент ам 2-3 курс ов м ат ем ат ичес кого факул ьт ет а, обучающим с я по с пециал ь нос т и/направ л ению «М ат ем ат ика» и направ л ению «М ат ем ат ика. Ком пь ют ерны е науки» .
П е ча та е тся по ре ш е н ию методиче ской комиссии ма тема тиче ског о фа кул ьте та Ива н овског ог осуда рстве н н ог о ун иве рсите та
Ре це н зе н т канд ид ат физ ико-м ат ем ат ичес кихнаук, д оцент Н . И . Я ц кин
Ó И з д ат ел ь с т в о«И в анов с кий гос уд арс т в енны й унив ерс ит ет » , 2005
СО Д Е РЖ А Н И Е В ведение ....................................................................................................... 4 1. М одуль но е п ро граммирование ............................................................ 6 1.1. М од ул и и ихс т рукт ура ................................................................... 6 1.2. И с пол ь з ов ание м од ул ей ................................................................ 11 1.3. Ос обеннос т и под кл ючения м од ул ей ............................................ 13 Упражнения ........................................................................................... 15 2. О б ъектно е п ро граммирование .......................................................... 16 2.1. Кл ас с ы и объект ы .......................................................................... 16 2.2. И с пол ь з ов ание кл ас с ов ................................................................. 18 2.3. Реал из ация кл ас с а ......................................................................... 22 2.4. Обл ас т и в ид им ос т и чл енов кл ас с а .............................................. 23 2.5. Конс т рукторы и д ес т рукторы ....................................................... 30 Упражнения ........................................................................................... 33 3. О б ъектно -о риентированно е п ро граммирование ........................... 34 3.1. Н ас л ед ов ание ................................................................................. 34 3.2. Сов м ес т им ос т ь кл ас с ов и ее ос обеннос т и .................................. 40 3.3. Опред ел ение т ипа объект а в ов рем я в ы пол нения ...................... 42 3.4. Ст ат ичес кое и д инам ичес кое с в яз ы в ание ................................... 45 3.5. Абс т ракт ны е м етод ы и кл ас с ы ..................................................... 51 Упражнения ........................................................................................... 55 4. Реализац ияо б ъектно й модели ........................................................... 56 4.1. Указ ат ел и на под програм м ы ......................................................... 56 4.2. Абс т ракт ны е кл ас с ы и обобщенны е ал горит м ы ......................... 59 4.3. Н ас л ед ов ание ................................................................................. 62 4.4. Динам ичес кое с в яз ы в ание ............................................................ 66 4.5. Вопрос ы опт им из ации .................................................................. 69 Заклю чение ............................................................................................... 77 Ч точит ат ь д ал ь ш е? .............................................................................. 79
3
В В Е Д Е НИЕ Объект но-ориент иров анное програм м иров ание пол учил орас прос т ранение в о в торой пол ов ине 80-хгод ов прош л ого в ека прежд е в с его как э ффект ив ная т ехнол огия раз работ ки бол ь ш ихпроектов . Как с л ед с т в ие, его ид еол огию и преим ущес т в а л егче понят ь чел ов еку, уже им еющем у опы т под обной работ ы с ис пол ь з ов анием т рад иционны хс ред с т в . В тоже в рем я в ряд л и цел ес ообраз ноприобрет ат ь т акой опы т л иш ь рад и из учения нов огопод ход а. В нас тоящем пос обии пред принят а попы т ка показ ат ь , как пол учит ь в ы игры ш от ис пол ь з ов ания объект ной т ехнол огии д аже в от нос ит ел ь но небол ь ш ихпрограм м ах. И з л ожение с т ав ит с в оей цел ь ю в ы пол нит ь наибол ее пл ав ны й переход от процед урногок объект но-ориент иров анном у програм м иров анию, не т ребуя от чит ат ел я с раз у же начат ь «м ы с л ит ь в т ерм инахООП» . Пред пол агает с я, чтоз наком с т в ос нов ы м и в оз м ожнос тям и и прим ерам и их прим енения пом ожет програм м ис т у оценив ат ь э ффект от ис пол ь з ов ания объект ногопод ход а в егопроект е и раз рабат ы в ат ь с т рукт уру кл ас с ов , ис ход я из ожид аем ы хрез ул ь т атов . Пос кол ь ку из д ание ориент иров анов перв ую очеред ь на с л уш ат ел ей кл ас с ичес кихунив ерс ит етов , в нем уд ел яет с я опред ел енное в ним ание с в яз ям програм м иров ания и т еорет ичес кой м ат ем ат ики. Раз в ет в л енная с ис т ем а абс т ракт ны хпонят ий пос л ед ней поз в ол яет л егкопрод ем онс т риров ат ь как преим ущес т в а нов ы хм еханиз м ов , т ак и ограниченнос т ь ихв оз м ожнос т ей. И з л ожение в д анном пос обии в ед ет с я с ис пол ь з ов анием яз ы ка Object Pascal, которы й яв л яет с я час т ь ю с ред ы раз работ ки Borland Delphi (в с е прив од им ы е прим еры т ес т иров ал ис ь в с ед ь м ой в ерс ии пакет а). Х орош оиз в ес т но, чтоПас кал ь раз рабат ы в ал с я Н . Виртом прежд е в с егокак учебны й яз ы к, и Object Pascal в опред ел енной м ере унас л ед ов ал э т у ос обеннос т ь . От с ут с т в ие в нем м ногихв оз м ожнос т ей, прис ущих C++ и Java, на начал ь ном э т апе из учения оказ ы в ает с я с корее преим ущес т в ом , чем нед ос т ат ком . Вм ес т е с т ем , объект ны е м од ел и э т ихт рехяз ы ков им еют м ногообщего, т ак чтос фера прим енения пол ученны хз наний не ограничив ает с я л иш ь програм м иров анием в Delphi. Перв ая час т ь пос обия с од ержит необход им ы е с в ед ения о с оз д ании библ иот ек. Х отя раз биение ис ход ного код а проект а на отд ел ь ны е м од ул и не им еет прям огоот нош ения к объект ном у програм м иров анию, без него не м огут бы т ь в пол ной м ере реал из ов аны абс т ракт ны е т ипы д анны х, опис анию раз работ ки которы хпос в ящена в торая час т ь . Т рет ь я 4
час т ь показ ы в ает, каким образ ом м еханиз м ы объект но-ориент иров анногопрограм м иров ания ис пол ь з уют с я д л я с оз д ания обобщенны хал горит м ов , прим еним ы хк д анны м пот енциал ь но бес конечногом ножес т в а т ипов . Н аконец, в чет в ертой час т и рас с м ат рив ают с я д в е нес кол ь кораз л ичны е реал из ации объект ной м од ел и и произ в од ит с я с рав нение в оз м ожнос т ей нов ой т ехнол огии и процед урногопрограм м иров ания. Сл ед ует от м ет ит ь , что круг в опрос ов , с в яз анны х с объект ны м под ход ом , не ис черпы в ает с я перечис л енны м и т ем ам и. Пол нос т ь ю з а рам кам и обс ужд ения ос т ал ис ь , в час т нос т и, кл ас с ы -конт ейнеры и м ножес т в енное нас л ед ов ание. Поэ той причине в пос обии не упом инают с я кл ас с ов ы е м етод ы и с с ы л ки, инт ерфейс ы объектов . Пред пол агает с я, чточит ат ел ь буд ет з наком ит ь с я с м атериал ом пос л ед ов ател ь но; текс т, которы й при перв ом прочт ении м ожно опус т ит ь , в ы д ел яет с я м ел ким ш рифтом . Дл я поним ания прим еров т ребует с я им еть пред с т ав л ение об ос нов ны хконс т рукцияхи т ипахяз ы ка Пас кал ь , в кл ючая з апис и, а т акже ос пос обахд инам ичес когоуправ л ения пам ят ь ю.
5
1. М О Д У Л ЬН О Е ПРО Г РА М М И РО В А Н И Е 1.1. М одули и их структура Соз д ание м од ул ей яв л яет с я с в яз ующим з в еном м ежд у процед урно-ориент иров анны м програм м иров анием , которое бы л онаибол ее попул ярной парад игм ой раз работ ки програм м ного обес печения в 1970-хгод ах, и информ ационно-ориент иров анны м (объект ны м ) програм м иров анием , с м енив ш им егов 1980-х. М одул ем в Object Pascal наз ы в ает с я с пециал ь ны м образ ом оформ л енная библ иот ека под програм м (процед ур и функций), которая м ожет т акже с од ержат ь объяв л ения нов ы хт ипов д анны х, перем енны хи конс т ант. Как и програм м у в цел ом , м од ул ь м ожнос ком пил иров ат ь . Рез ул ь т атом ком пил яции яв л яет с я файл , с очет ающий м аш инны й (пл ат форм оз ав ис им ы й) код под програм м м од ул я с т екс тов ы м и д анны м и: объяв л ениям и т ехже под програм м , а т акже т ипов , перем енны хи конс т ант, в в од им ы х в м од ул е. Сам ос тоят ел ь но з апус т ит ь на в ы пол нение э тот файл нел ь з я, од накоинформ ация из негов пос л ед с т в ии м ожет бы т ь ис пол ь з ов ана ком понов щиком (linker) д л я с борки програм м , в которы хим еют с я с с ы л ки на чл ены м од ул я. При э том упом янут ы е в ы ш е т екс тов ы е д анны е в ы с т упают в качес т в е опис ания с од ержим ого файл а, т ак что ис ход ны й код библ иот еки на э том э т апе оказ ы в ает с я уже не нужны м . Ос нов ное наз начение м од ул ей с ос тоит в раз биении бол ь ш ихпрограм м на от нос ит ел ь но нез ав ис им ы е час т и, с од ержащие л огичес ки с в яз анны е м ежд у с обой код и д анны е. Под обное раз биение упрощает с т руктуру програм м ы и поз в ол яет раз рабаты в ать отд ел ь ны е ее час т и нез ав ис им ои парал л ел ь но(в том чис л е раз л ичны м и л юд ь м и). Пом им оэ тогом од ул и неред ко в ы с тупают и в качес т в е конечного прод укт а, ес л и цел ь ю проект а яв л яет с я с оз д ание библ иот еки, которая м ожет м ногократнои без каких-л ибо из м енений ис пол ь з ов ат ь с я в раз ны хпрограм м ах. Как бы л о отм ечено в ы ш е, д л я под кл ючения т акой библ иот еки д ос т аточно л иш ь с ком пил иров анны хфайл ов , поэ том у появ л яет с я в оз м ожнос т ь раз работ ки ком м ерчес кихпрод уктов , не пред ос т ав л яющихд ос тупа к ис ход ном у код у. В Object Pascal ис ход ны й т екс т м од ул я хранит с я в од ном файл е с рас ш ирением pas. Э тот файл начинает с я с з арез ерв иров анного с л ов а unit (м од ул ь ), з а которы м через пробел с л ед ует им я м од ул я, з ав ерш аем ое точкой с з апятой. И м я м од ул я д ол жно с ов пад ат ь с им енем файл а, с од ержащегоегоис ход ны й код (в кл ючая регис т р с им в ол ов ). Заканчив а6
ет с я файл з арез ерв иров анны м с л ов ом end с точкой на конце. Прос т ранс т в о м ежд у з агол ов ком м од ул я и з ав ерш ающим end. раз бив ает с я на чет ы ре ра здел а : ин те рфе йса , ре а л иза ции, ин ициа л иза ции и фин а л иза ции (с л ед ующихим еннов т аком поряд ке). Раз д ел реал из ации начинает с я с кл ючев огос л ов а implementation и с инт акс ичес ки почт и ид ент ичен програм м е с той л иш ь раз ницей, что не с од ержит гл ав ногобл ока begin ¼ end. Б ол ее точноэ тооз начает, что з д ес ь м ожет рас пол агат ь с я л юбое кол ичес т в о опред ел ений процед ур и функций, с екций объяв л ения т ипов , перем енны хи конс т ант, с л ед ующих в произ в ол ь ном поряд ке. При э том , од нако, не с л ед ует з абы в ат ь , что ид ент ификаторы , как прав ил о, д ол жны бы т ь объяв л ены д ос в оегоперв огоис пол ь з ов ания. Раз д ел объяв л ений ил и инт ерфейс а (interface) м ожет с од ержат ь объяв л ения т ипов , перем енны хи конс т ант, им ена которы хд ол жны бы т ь уникал ь ны в пред ел ахм од ул я. Кром е того, с юд а пом ещают объяв л ения некоторы х(необяз ат ел ь но в с ех) под програм м , опред ел енны хв раз д ел е реал из ации 1. Е с л и объяв л ение под програм м ы наход ит с я в раз д ел е инт ерфейс а, тов раз д ел е реал из ации с пис ок ее парам ет ров м ожноопус т ить . В прот ив ном с л учае он д ол жен в точнос ти с оот в ет с тв ов ать прив ед енном у ранее. Вс е чл е н ы м од ул я (т ипы д анны х, перем енны е, конс т ант ы , процед уры и функции), перечис л енны е в раз д ел е инт ерфейс а, наз ы в ают с я открытыми ( public); чл ены , объяв л енны е л иш ь в раз д ел е реал из ации — за крытыми ( private). Объяс нение э т им т ерм инам буд ет д анов с л ед ующем параграфе. Раз д ел ы инициал из ации и финал из ации (начинающиес я с л ов ам и initialization и finalization, с оот в ет с т в енно) яв л яют с я необяз ат ел ь ны м и. Кром е того, раз д ел финал из ации м ожет ис пол ь з ов ат ь с я л иш ь в м од ул ях, с од ержащихбл ок инициал из ации. Синт акс ичес ки оба э т ихраз д ел а э кв ив ал ент ны т ел у процед уры ил и функции. В час т нос т и, они не д ол жны с од ержат ь никакихобъяв л ений. 1
Зд ес ь и д ал ее под объявл е н ием под програм м ы поним ает с я в ы ражение, которое с ос тоит из кл ючев огос л ов а procedure ил и function, з а которы м с л ед уют им я под програм м ы , с пис ок ее парам ет ров и т ип в оз в ращаем огоз начения (в с л учае функции). Пол ное опис ание под програм м ы , в кл ючающее ее з агол ов ок (header), т ел о(body) и перечень л окал ь ны хконс т ант, перем енны хи под програм м , наз ы в ает с я определ е н ием. Э т а т ерм инол огия отл ичает с я от принятой в оригинал ь ной д окум ент ации, гд е опред ел ение (в наш ем с м ы с л е) наз ы в ает с я объяв л ением (declaration).
7
Ос нов ное наз начение раз д ел а инициал из ации — з ад ание с т артов ы х з начений перем енны х (наприм ер, с пом ощь ю д ат чика с л учайны х чис ел ) и раз м ещение в пам ят и д инам ичес кихс т рукт ур д анны х. Раз д ел финал из ации ис пол ь з ует с я д л я ос в обожд ения рес урс ов , которы е м огл и бы т ь з анят ы в процес с е в ы пол нения раз д ел а инициал из ации и под програм м из раз д ел а реал из ации. Т ипичны м и з ад ачам и яв л яют с я уд ал ение д инам ичес ки с оз д анны хперем енны х, з акры т ие файл ов и т. п. Сл ед ует учит ы в ат ь , что раз д ел финал из ации м ожет бы т ь в ы з в ан д оз ав ерш ения раз д ел а инициал из ации. Т акая с ит уация в оз никает, ес л и в процес с е в ы пол нения пос л ед негопояв л яет с я ош ибка ил и, гов оря бол ее точно, необработ анная ис кл ючит ел ь ная с ит уация. В з акл ючение э тогопараграфа прив ед ем прим ер реал из ации библ иот еки д л я работ ы с рационал ь ны м и чис л ам и. Она в кл ючает опред ел ения нов огот ипа Rational — з апис и с д в ум я пол ям и цел огот ипа num и den д л я хранения чис л ит ел я и з нам енат ел я — и в ос ь м и под програм м , работ ающихс д анны м и э тогот ипа. Перв ы е чет ы ре: функции Plus, Minus, Dot и Slash, пред с т ав л яют с обой обы чны е операторы с л ожения, в ы чит ания, ум ножения и д ел ения рационал ь ны хчис ел . Ос т ав ш иес я процед уры реал из уют т ак наз ы в аем ы е опе ра торы с присвое н ием. И хотл ичие с ос тоит в том , чторез ул ьт ат в ы пол нения с оотв ет с т в ующей операции с охраняет с я в перв ом аргум ент е. Т ак, наприм ер, в ы з ов процед уры Add: Add(r1, r2);
э кв ив ал ент ен в ы ражению r1 := Plus(r1, r2);
Очев ид но, что ис пол ь з ов ание перв ой инс т рукции э ффект ив нее: ис чез ает л иш няя операция прис в аив ания. Кром е того, в с л ед ующей час т и м ы ув ид им , чтораз рабат ы в ат ь и ис пол ь з ов ать операторы с прис в оением иногд а оказ ы в ает с я проще, чем обы чны е ал гебраичес кие операции. Пример 1.1. Б ибл иот ека д л я работ ы с рационал ь ны м и чис л ам и. unit UnitRational; interface // объявление типа Rational type Rational = record // рациональное число num: Integer; // числитель (numerator) den: Integer; // знаменатель (denominator) end;
8
// объявления подпрограмм function Plus(r1,r2:Rational): Rational; function Minus(r1,r2:Rational): Rational; function Dot(r1,r2:Rational): Rational; function Slash(r1,r2:Rational): Rational; procedure Add(var r1:Rational; r2:Rational); procedure Subtract(var r1:Rational; r2:Rational); procedure MultiplyBy(var r1:Rational; r2:Rational); procedure DivideBy(var r1:Rational; r2:Rational);
// // // // // // // //
Плюс Минус Точка Косая черта Прибавить Вычесть УмножитьНа РазделитьНа
{ Поскольку результат выполнения перечисленных выше процедур сохраняется в первом аргументе, этот аргумент должен быть передан по ссылке, а не по значению. } implementation uses SysUtils; // модуль включает поддержку исключений procedure Normalize(var r:Rational); { Процедура приводит рациональное число r, передаваемое в качестве параметра, к нормальной форме: числитель - целое число, знаменатель - натуральное. } begin if r.den=b then a:=a-b else b:=b-a; // по завершении цикла b=НОД(r.num,r.den) r.num:=r.num div b; r.den:=r.den div b; end; // определения подпрограмм, объявленыых в разделе интерфейса function Plus(r1,r2:Rational): Rational; var res: Rational; begin res.num:=r1.num*r2.den+r1.den*r2.num; res.den:=r1.den*r2.den; Normalize(res); Reduce(res);
9
result:=res; { Последняя инструкция эквивалентна выражению Plus:=res; Локальная переменная result неявно объявляется в каждой функции и имеет тип, совпадающий с типом возвращаемого значения. По завершении работы функции содержимое этой переменной передается вызывающей программе. } end; procedure Add(var r1:Rational; r2:Rational); var _num,_den:Integer; begin _num:=r1.num*r2.den+r1.den*r2.num; _den:=r1.den*r2.den; r1.num:=_num; r1.den:=_den; Normalize(r1); Reduce(r1); end; function Slash(r1,r2:Rational): Rational; var res: Rational; begin if r2.num=0 then raise Exception.Create('Division by zero'); { Если числитель второго аргумента равен нулю, возбуждается исключение с сообщением "Деление на ноль". } res.num:=r1.num*r2.den; res.den:=r1.den*r2.num; Normalize(res); Reduce(res); result:=res; end; procedure DivideBy(var r1:Rational; r2:Rational); var _num,_den:Integer; begin if r2.num=0 then raise Exception.Create('Division by zero'); _num:=r1.num*r2.den; _den:=r1.den*r2.num; r1.num:=_num; r1.den:=_den; Normalize(r1); Reduce(r1); end; ... { Определение оставшихся четырех процедур и функций совершенно аналогично и потому здесь опускается. В реальном коде оно обязательно должно присутствовать. } end.
10
Отл ичит ел ь ной ос обеннос т ь ю функции Slash и процед уры DivideBy яв л яет с я час т ичны й характ ер в ы пол няем ы хим и операций. Е с л и в торой ихаргум ент оказ ы в ает с я рав ны м нул ю, в оз никает искл ю чител ьн а я ситуа ция — с ос тояние програм м ы , при котором д ал ь нейш ее в ы пол нение т екущей под програм м ы нев оз м ожно. Воз бужд ение ис кл ючения, ос ущес т в л яем ое оператором raise, поз в ол яет прерв ат ь в ы чис л ения и пред ос т ав ит ь в ы з ы в ающей програм м е прав ос ам ой принят ь реш ение, как преод ол ет ь появ ив ш уюс я неод ноз начнос т ь . Она м ожет л ибо обра бота ть искл ю чител ьн ую ситуа цию , ес л и т а не яв л яет с я крит ичной д л я ос нов ного ал горит м а, л ибов с в ою очеред ь прекрат ит ь в ы пол нение с в ы д ачей с оот в ет с т в ующего с ообщения пол ь з ов ател ю. По ум ол чанию ис пол ь з ует с я в торой в ариант. М еханиз м ис кл ючений яв л яет с я э ффект ив ной ал ьт ернат ив ой за щищ е н н ой те хн ике прог ра ммирова н ия, ос нов анной на анал из е в оз в ращаем ы хт ем ил и ины м с пос обом код ахош ибки. 1.2. И сп о ль зование модулей Соз д анны й м од ул ь м ожет бы т ь ис пол ь з ов ан как в ос нов ной програм м е, т ак и в д ругом м од ул е; ихназ ы в ают кл ие н та ми д анногом од ул я. Под кл ючение ос ущес т в л яет с я пос ред с т в ом оператора uses (ис пол ь з ует ): uses ИмяМодуля;
В програм м е в с е операторы uses д ол жны с тоят ь с раз у пос л е з агол ов ка, в м од ул е — пос л е с л ов interface ил и implementation. В од ном операторе uses м ожноперечис л ит ь и нес кол ь коим ен, раз д ел ив ихз апят ы м и. Пос л е под кл ючения м од ул я кл иент у с т анов ят с я д ос т упны л иш ь его от кры т ы е чл ены (т. е. т е, которы е бы л и объяв л ены в с екции инт ерфейс а). Обращение к ним произ в од ит с я т ак, как ес л и бы они бы л и объяв л ены в с ам ом кл иент е. В час т нос т и, перем енны е и конс т ант ы с т анов ят с я гл обал ь ны м и. Воз м ожна, од нако, с ит уация, когд а раз ны е м од ул и с од ержат от кры т ы е чл ены с од инаков ы м и им енам и. В э том с л учае обращение к чл ену конкрет ногом од ул я ос ущес т в л яет с я при пом ощи в ы ражения ИмяМодуля.ИмяЧлена
Е с л и ис пол ь з ует с я т акая з апис ь , тогов орят, чтоим я чл ена ква л ифицирова н о им енем м од ул я. Б ол ее под робно пробл ем а перекры в ающихся объяв л ений рас с м ат рив ает с я в § 1.3.
11
В качес т в е прим ера рас с м от рим небол ь ш ую програм м у, т ес т ирующую библ иот еку из пред ы д ущегопараграфа. Пример 1.2. Т ес тов ая програм м а д л я библ иот еки из прим ера 1.1. program TestRational; {$APPTYPE CONSOLE} // директива компилятора, определяющая консольное // приложение uses UnitRational; // подключаем модуль нашей библиотеки var r1: Rational = (num: 1; den: 2); r2: Rational = (num: -2; den: 6); ra,rs,rm,rd: Rational; { Поскольку тип Rational объявлен в интерфейсной части модуля, мы можем использовать его для объявления переменных. После старта приложения переменные r1 и r2 инициализируются значениями 1/2 и -2/6. } begin ra:=Plus(r1,r2); // обращение к функциям и процедурам модуля rs:=Minus(r1,r2); // осуществляется просто по их именам, rm:=Dot(r1,r2); // однако допустимы и выражения вида rd:=Slash(r1,r2); // ra:=UnitRational.Plus(r1,r2); WriteLn('Plus: ',ra.num,'/',ra.den); WriteLn('Minus: ',rs.num,'/',rs.den); WriteLn('Dot: ',rm.num,'/',rm.den); WriteLn('Slash: ',rd.num,'/',rd.den); Add(ra,r2); Subtract(rs,r2); MultiplyBy(rm,r2); DivideBy(rd,r2); WriteLn('Add: ',ra.num,'/',ra.den); WriteLn('Sub: ',rs.num,'/',rs.den); WriteLn('Mul: ',rm.num,'/',rm.den); WriteLn('Div: ',rd.num,'/',rd.den); ReadLn; // ввод необходим только для предотвращения // автоматического закрытия окна консоли end.
В процес с е работ ы програм м а в ы в од ит с л ед ующую информ ацию: Plus: Minus: Dot: Slash:
1/6 5/6 -1/6 -3/2
12
Add: Sub: Mul: Div:
-1/6 7/6 1/18 9/2
Зд ес ь с т роки 3 и 7 д ем онс т рируют, в час т нос т и, коррект ную работ у процед уры Reduce, а 4 и 8 — т акже и процед уры Normalize. Обе они яв л яют с я з акры т ы м и, поэ том у непос ред с т в енное упот ребл ение в т ес тов ой програм м е в ы ражений т ипа Normalize(r2); Reduce(r2); прив ед ет к ош ибке на э т апе ком пил яции. В д ейс т в ит ел ь нос т и, раз д ел ение чл енов м од ул ей на от кры т ы е и з акры т ы е яв л яет с я од ним из ос нов ны хпреим ущес т в ис пол ь з ов ания пос л ед них. Онопоз в ол яет с кры т ь от кл иент а час т ь реал из ации ал горит м а, которую в пос л ед с т в ии м ожнобуд ет м од ифициров ат ь , не в нос я никаких из м енений в ис ход ны й код д анногокл иент а. Б ол ее того, ес л и библ иот ека яв л яет с я д инам ичес ки з агружаем ой, тоее кл иент ы не прид ет с я д аже переком пил иров ат ь . 1.3. О со б енно сти п одклю чениямодулей В э том параграфе нам буд ет уд обнос чит ат ь ос нов ную програм м у м од ул ем , в котором нет раз д ел а инт ерфейс а, а рол ь раз д ел ов инициал из ации и финал из ации играет гл ав ны й бл ок begin ¼ end. Операторы uses опред ел яют от нош ения з ав ис им ос т и м ежд у м од ул ям и, которы е очев ид ны м образ ом м огут бы т ь пред с т ав л ены в в ид е ориент иров анного г ра фа за висимосте й. Е с л и с ущес т вует пут ь , с в яз ы в ающий в э том графе в ерш ину, с оот в ет с т в ующую м од ул ю A, с в ерш иной, с оотв ет с т в ующей м од ул ю B, тогов орят, чтом од ул ь A косве н н о испол ьзуе т м од ул ь B. Пос кол ь ку граф з ав ис им ос т ей м ожет им ет ь практ ичес ки л юбой в ид , в оз м ожнос т ь кос в енного ис пол ь з ов ания порожд ает некоторы е пробл ем ы , которы е необход им оучит ы в ать при раз работ ке м од ул ей. Прежд е в с его з ам ет им , что м од ул ь м ожет кос в енно ис пол ь з ов ат ь с ам с ебя. Т акая с итуация с оот в ет с т в ует цикл у на графе и наз ы в ает с я цикл иче ской ссыл кой м од ул ей. Ком пил ятор з апрещает цикл ичес кую с с ы л ку, ес л и в с е с оотв ет с т в ующие ей операторы uses рас пол ожены в инт ерфейс ны хчас тяхм од ул ей. Т ем с ам ы м ис кл ючает с я в оз м ожнос т ь появ л ения с ам ос с ы л ающихсяобъяв л ений т ипов д анны х. От с юд а в ы т екает с л ед ующее прав ил о: под кл ючение м од ул я в раз д ел е инт ерфейс а в ы пол няет с я л иш ь тогд а, когд а его перем енны е, конс т ант ы ил и т ипы ис пол ь з уют с я в объяв л енияхд анногораз д ел а. Вов с ех 13
ос т ал ь ны хс л учаяхс оот в ет с т в ующий оператор uses пом ещает с я в раз д ел реал из ации. Поряд ок под кл ючения м од ул ей опред ел яет и поряд ок с рабат ы в ания ихраз д ел ов инициал из ации и финал из ации, причем с ущес т в енны м и з д ес ь оказ ы в ают с я не тол ь ков ид графа з ав ис им ос т ей, нои очеред нос т ь перечис л ения м од ул ей в операторах uses. Пос л ед ов ат ел ь нос т ь в ы пол нения э т ихраз д ел ов опред ел яет с я инд укт ив нос л ед ующим образ ом . Дл я м од ул я, не ис пол ь з ующегод ругихм од ул ей, процед урой инициал из ации буд ем наз ы в ат ь прос той в ы з ов его раз д ел а инициал из ации, ес л и тол ь коон уже не бы л в ы пол нен ранее. Пус т ь т еперь м од ул ь A под кл ючает м од ул и B1, B2, ¼, Bn (им еннов т аком поряд ке). Тогд а процед ура инициал из ации м од ул я A буд ет с ос тоят ь в пос л ед ов ат ел ь ном в ы з ов е процед ур инициал из ации м од ул ей B1, B2, ¼, Bn и з ав ерш ат ь с я в ы пол нением раз д ел а инициал из ации м од ул я A (с нов а при ус л ов ии, что э то не бы л ос д ел аноранее). Т аким образ ом , процед ура инициал из ации ос нов ной програм м ы прив од ит к од нократ ном у ис пол нению раз д ел ов инициал из ации в с ехм од ул ей, кос в енноею ис пол ь з уем ы х. Раз д ел ы финал из ации в ы з ы в ают с я в обрат ном поряд ке. Рас с м от рим небол ь ш ой прим ер. Пус т ь програм м а Program1 с од ержит оператор uses Unit1, Unit2, Unit3; и пус т ь м од ул и Unit1 и Unit2 т акже ис пол ь з уют м од ул ь Unit3. Т огд а граф з ав ис им ос т ей м од ул ей в ы гл яд ит с л ед ующим образ ом : Program1 Unit1
Unit2
Unit3
Пос л е с т арт а прил ожения начинает с я инициал из ация ос нов ной програм м ы и перв ой в ы з ы в ает с я процед ура инициал из ации м од ул я Unit1. Пос кол ь ку он ис пол ь з ует Unit3, то с начал а в ы пол няет с я раз д ел инициал из ации Unit3, а з ат ем — Unit1. Дал ее с л ед ует процед ура инициал из ации м од ул я Unit2. Т ак как Unit3 уже бы л инициал из иров ан, она с в од ит с я к в ы з ов у раз д ел а инициал из ации Unit2. Т рет ь ей пос чет у в ы пол няет с я процед ура инициал из ации Unit3, которая прос то ничего не д ел ает. Т еперь нас тупает черед ос нов ного бл ока програм м ы , по з ав ерш ении работ ы которого раз д ел ы финал из ации м од ул ей ис пол няют с я в обрат ном поряд ке: Unit2, Unit1, Unit3. Э тот прим ер показ ы в ает, в час т нос т и, что пос л ед ов ат ел ь нос т ь инициал из ации м од ул ей не в с егд а очев ид на раз работ чику програм м ы . 14
Поэ том у в д окум ент ации к некоторы м библ иот екам жес т коогов арив ают пос л ед ов ат ел ь нос т ь их под кл ючения. Реком енд ует с я т акже перв ы м и в операторахuses указ ы в ат ь с т анд арт ны е м од ул и Delphi. Раз работ чик с ис т ем ы библ иот ек, раз ум еет с я, т акже д ол жен учит ы в ат ь опис анную в ы ш е неод ноз начнос т ь . Пробл ем ы з д ес ь м огут бы т ь с в яз аны , в час т нос т и, с попы т кам и раз л ичны хм од ул ей з ахв ат ит ь од ни и т е же рес урс ы . Преод ол ет ь э т у неприят нос т ь м ожно, наприм ер, пос ред с т в ом ус т анов ки с оот в ет с т в ующихфл агов . Н аконец, еще од на с л ожнос т ь в ы з в ана т ем , чтов раз л ичны хм од ул яхм огут бы т ь объяв л ены чл ены с од ним и и т ем и же им енам и. Э т и чл ены с кры в ают д руг д руга и кл ючев ую рол ь з д ес ь с нов а играет поряд ок перечис л ения м од ул ей в операторе uses. Е с л и м од ул ь A пос л ед ов ат ел ь но под кл ючает м од ул и B1, B2, ¼, Bn, то объяв л ения м од ул я Bi + 1 с кры в ают объяв л ения м од ул я Bi, а объяв л ения м од ул я A — в с е объяв л ения м од ул ей Bk, 1 £ k £ n. Т ем не м енее, д ос туп к чл енам конкрет ного м од ул я в с егд а м ожнопол учит ь , кв ал ифициров ав им яэ тогочл ена им енем м од ул я. В качес т в е ил л юс т рации с нов а рас с м от рим прим ер, прив ед енны й в ы ш е. Пред пол ожим , чтом од ул ь Unit3 с од ержит от кры т ую перем енную x т ипа Integer, а м од ул ь Unit2 — перем енную с т ем же им енем , но уже т ипа Real. Т огд а в м од ул яхUnit1 и Unit3 перем енная x буд ет цел ой, а в м од ул е Unit2 — д ейс т в ит ел ь ной, т ак как в нем объяв л ение из м од ул я Unit3 с кры в ает с я с обс т в енны м . В ос нов ной програм м е перем енная x с нов а буд ет цел ой, пос кол ь ку пос л ед ним в операторе uses с тоит Unit3, д ос т уп же к в ещес т в енной перем енной м од ул я Unit2 ос ущес т в л яет с я с пом ощь ю в ы ражения Unit2.x. У п раж нения 1.1. Раз работ айт е библ иот еку д л я работ ы с цел очис л енны м и в екторам и д л ины n, гд е n — некоторая конс т ант а. У казание. Пом им о из в ес т ны хм ат ем ат ичес кихопераций д л я нов огот ипа раз ум ноопред ел ит ь под програм м ы , которы е реал из уют д ейс т в ия, с пецифичны е д л я програм м иров ания: прис в аив ание, с рав нение, с оз д ание копии.
1.2. Т а же з ад ача, но д л я м ат риц раз м ера n ´ n, эл ем ент ам и которы х яв л яют с я рационал ь ны е чис л а. При в ы пол нении арифм ет ичес ких операций в э том с л учае с л ед ует ис пол ь з ов ат ь под програм м ы из м од ул я UnitRational.
15
2. О Б ЪЕ К Т Н О Е ПРО Г РА М М И РО В А Н И Е 2.1. К лассы и о б ъекты Б ибл иот ека, пос т роенная в параграфе 1.1, им еет ряд нед ос т ат ков . Во-перв ы х, не в с якое з начение перем енной т ипа Rational, д опус т им ое с точки з рения ком пил ятора, яв л яет с я т аков ы м и с точки з рения л огики програм м ы . Т ак, наприм ер, ес л и оба пол я num и den некоторой з апис и r с од ержат нул и (а им еннот акие з начения они пол учают при с т ат ичес ком раз м ещении перем енной в пам ят и), то перед ача r в качес т в е перв огопарам ет ра л юбой из от кры т ы хпод програм м библ иот еки прив од ит к бес конечном у в ы пол нению цикл а в процед уре Reduce и, как с л ед с т в ие, к з ав ис анию програм м ы . Т аким образ ом , програм м ис т, ис пол ь з ующий библ иот еку, пос тояннод ол жен с л ед ит ь з а т ем , чтобы пол я в с ех ис пол ь з уем ы хим перем енны хим ел и д опус т им ы е з начения. Н а э том ожнов оз раз ит ь , прав д а, чтопров ерку з начений парам ет ров на коррект нос т ь с л ед ует прос то д обав ит ь к реал из ации операций. Од наков с л ожны хал горит м ахв ы з ов ы под програм м проис ход ят гораз д о чаще, чем яв ное прис в аив ание, поэ том у т акое реш ение прив ед ет к с нижению с корос т и ихв ы пол нения. Вторая пробл ем а м енее очев ид на, нот акже в ес ь м а с ущес т в енна. И нт ерфейс м од ул я UnitRational показ ы в ает, что к перем енны м объяв л енного в нем т ипа прим еним ы операции с л ожения, в ы чит ания, ум ножения и д ел ения. Вм ес т е с т ем нет никакогос пос оба форм ал ь ногоопред ел ения того, чтот а ил и иная операция, наприм ер, в з ят ие ос т ат ка от д ел ения, к ним н е приме н има . Пол ь з ов ат ел ь библ иот еки в ообще не обяз ан с т роит ь с в ои програм м ы л иш ь на пред ос т ав л енны хв его рас поряжение процед урахи функциях, в м ес то э того он м ожет факт ичес ки нарав не в раз работ чиком с оз д ав ат ь с обс т в енны е под програм м ы , оперирующие д анны м т ипом . В д ейс т в ит ел ь нос т и, от м еченны е неприят нос т и яв л яют с я час т ны м и с л учаям и бол ее общей пробл ем ы : от кры тос т и в нут ренней с т рукт уры т ипа Rational. В пред ы д ущей час т и м ы уже гов орил и о том , что с окры т ие реал из ации библ иот еки с оз д ает в оз м ожнос т ь ее из м енения без с оот в ет с т в ующей м од ификации код а кл иентов . Т очно т ак же с окры т ие реал из ации т ипа д анны хд ает програм м ис т у-раз работ чику пол ную с в обод у в в ы боре конкрет ного пред с т ав л ения э того т ипа и в оз м ожнос т ь конт рол я цел ос т нос т и егообъектов . 16
Н о ес л и с т рукт ура т ипа не в ид на пол ь з ов ат ел ю, то что же тогд а с л ужит егоопис анием ? В качес т в е т аков огот еперь в ы с т упают свойства объектов д анного т ипа, то ес т ь операции, которы е к ним прим еним ы . Т ип д анны хс ос кры т ы м в нут ренним пред с т ав л ением , опис анны й в т ерм инахд опус т им ы хопераций, наз ы в ают а бстра ктн ым. Зам ет им , чтоабс т ракт ны е т ипы им еют м ногообщегос понят иям и с ов рем енной м ат ем ат ики. Кажд ое в в ед ение в т еорию м ножес т в от м ечает, чтоприрод а ихэл ем ентов не им еет никакогоз начения: м ножес т в а и кл ас с ы опред ел яют с я прос то как с ущнос т и, над которы м и м ожно в ы пол нят ь опред ел енны е операции. Т оже с ам ое в ернои в от нош ении л юбого д ругого м ат ем ат ичес кого понят ия. Сл ед с т в ием т акого под ход а яв л яет с я пов ы ш енная рез ул ь т ат ив нос т ь : конечны й итог того ил и иного ис с л ед ов ания как прав ил ооказ ы в ает с я прим еним не к од ном у, а к цел ом у кл ас с у конкрет ны хобъектов . Абс т ракт ны е т ипы д анны х в ы пол няют анал огичную функцию, поз в ол яя с оз д ав ат ь ал горит м ы , не з ав ис ящие от реал из ации т ипа и потом у обл ад ающие з начит ел ь но бóл ь ш им в рем енем жиз ни. Б ол ее того, появ л яет с я в оз м ожнос т ь раз рабат ы в ат ь обобщ е н н ые а л г оритмы, которы е од нов рем еннои без каких-л ибоиз м енений м огут бы т ь прим енены к д анны м пот енциал ь нобес конечногом ножес т в а т ипов . В Object Pascal, как и в бол ь ш инс т в е д ругихс ов рем енны хяз ы ков програм м иров ания, абс т ракт ны е т ипы реал из уют с я пос ред с т в ом кл а ссов. Кл ас с ом з д ес ь наз ы в ает с я т ип д анны х, объед иняющий в с ебе с т рукт уру, анал огичную з апис и, и набор под програм м д л я работ ы с ней. Перем енны е кл ас с ов огот ипа наз ы в ают объе кта ми. Опред ел ение кл ас с а с ос тоит из д в ухчас т ей: ин те рфе йса и ре а л иза ции. И нт ерфейс раз м ещает с я в раз д ел е type и им еет с л ед ующий в ид : ИмяКласса = class СписокЧленов end;
гд е И м я Клас с а — л юбой д опус т им ы й ид ент ификатор, С пи с о кЧ лено в — с пис ок объяв л ений чл енов кл ас с а: пол е й и ме тодов (в оз м ожно, пус той). В д ейс т в ит ел ь нос т и, яз ы к Object Pascal ис пол ь з ует еще од ин т ип чл енов кл ас с а: свойства ( properties), которы й поз в ол яет с в яз ы в ат ь м ежд у с обой пол я и м етод ы . Св оим проис хожд ением он обяз ан, по-в ид им ом у, ос обеннос тям с ред ы раз работ ки, ис пол ь з уем ой Delphi. В отл ичие от с в ойс т в абс т ракт ны хт ипов , пол нос т ь ю опис ы в ающихв оз м ожнос т и экз ем пл яров , с в ойс т в а кл ас с а ис пол ь з уют с я в ос нов ном д л я пред с т ав л ения кол ичес т в енны ххаракт ерис т ик объект а. Н ичего принципиал ь но нов ого в объект ную м од ел ь с в ойс т в а не д обав л яют, поэтом у д ал ее м ы онихгов орит ь не буд ем .
17
Пол я кл ас с а, т ак же как и пол я з апис и, пред с т ав л яют с обой обы чны е перем енны е, с группиров анны е в од ну с т рукт уру. М етод ы — э то под програм м ы д л я работ ы с д анной с т рукт урой. Объяв л ения пол ей и м етод ов анал огичны объяв л ениям , с оот в ет с т в енно, перем енны хи под програм м . Рас с м от рим Пример 2.1. И нт ерфейс кл ас с а «Т реугол ь ник» . type Triangle = class a,b,c: Real; function Square: Real; function Perimeter: Real; end;
// // // //
класс треугольник поля - длины сторон метод для вычисления площади метод для вычисления периметра
Прив ед енное объяв л ение показ ы в ает, чтообъект ы кл ас с а Triangle характ ериз уют с я т рем я д ейс т в ит ел ь ны м и чис л ам и — д л инам и с торон, и что к кажд ом у объект у прим еним ы операции в ы чис л ения пл ощад и и перим ет ра. Отл ожим на в рем я в опрос о реал из ации м етод ов и пос м от рим , как ис пол ь з ов ат ь готов ы е кл ас с ы в програм м е. 2.2. И сп о ль зование классов Как и д ругие т ипы д анны х, кл ас с ы д ос т аточноред кофигурируют с обс т в еннов код е ал горит м ов . Обы чноихим ена упот ребл яют с я в объяв л енияхобъектов — перем енны хи парам ет ров под програм м . Ос обеннос т ь ю объект ной м од ел и яз ы ка Object Pascal яв л яет с я то, что в с е объект ны е перем енны е в нем пред с т ав л яют с обой указ ат ел и (ссыл ки н а объе кты, object reference), ис ход ны е з начения которы х не опред ел ены . Дл я реал ь ногораз м ещения объект а в пам ят и ис пол ь з ует с я с л ед ующая инс т рукция: ИмяОбъекта := ИмяКласса.Create;
Она в ы д ел яет в пам ят и обл ас т ь , с од ержащую по од ном у э кз ем пл яру кажд огопол я кл ас с а, и прис в аив ает объект ной перем енной ее ад рес . Т аким образ ом , в опреки перв ом у в печатл ению, объект ы им еют почт и т акое же в нут реннее с т роение, как и перем енны е т ипа «з апис ь » . М етод ы по-прежнем у раз м ещают с я в пам ят и тол ь коод ин раз , в обл ас т и, от в ед енной д л я код а, и ихобъед инение с пол ям и в объяв л ении кл ас с а
18
нос ит чис тос инт акс ичес кий характ ер2. Н екоторое с ход с т в ом ежд у прив ед енны м в ы ш е в ы ражением и инс т рукцией в оз бужд ения ис кл ючения raise Exception.Create(...) не с л учайно. В д ейс т в ит ел ь нос т и, в с е ис кл ючения в Object Pascal яв л яют с я объект ам и кл ас с а Exception и, в ы з ы в ая их, м ы перед аем оператору raise ад рес в нов ь с оз д анногоэкз ем пл яра д анногокл ас с а, с од ержащегоопис ание ис кл ючит ел ь ной с ит уации. Впос л ед с т в ии эт а информ ация м ожет бы т ь ис пол ь з ов ана при обработ ке ис кл ючения, од нако под робное з наком с т в о с д анны м процес с ом не в ход ит в наш и пл аны .
Пос л е в ы д ел ения пам ят и обращение к пол ям объект а произ в од ит с я пос ред с т в ом оператора «точка» : ИмяОбъекта.ИмяПоля
Операция раз ы м енов ы в ания (^), необход им ая при работ е с д инам ичес ким и перем енны м и д ругихт ипов , д л я объект ны хс с ы л ок не т ребует с я. Опис анию с инт акс ис а в ы з ов а м етод ов пред пош л ем небол ь ш ое от с т упл ение. Как из в ес т но, в м ат ем ат ике прим еняют с я д в а с пос оба з апис и отображений: функционал ь ны й x(a, b) и операторны й a x b. Перв ы й яв л яет с я бол ее унив ерс ал ь ны м и ис пол ь з ует с я в т еории функций. Второй в с очет ании с о с в ойс т в ом ас с оциат ив нос т и поз в ол яет из бежат ь л иш них с кобок при з апис и ком поз иции отображений и характ ерен д л я ал гебры . Абс ол ют но никакой с од ержат ел ь ной раз ницы м ежд у э т им и с пос обам и нет и в ы бор в пол ь з у того ил и иного опред ел яет с я, гл ав ны м образ ом , с л ожив ш им ис я т рад ициям и. Яз ы ки програм м иров ания обы чно под д ержив ают обе форм ы з апис и, рас ш иряя как понят ие оператора, т ак и понят ие функции. С появ л ением объектов к э т им форм ам д обав л яет с я еще од на, нес кол ь ков арь ирующаяс я от од ногояз ы ка к д ругом у. В Object Pascal д л я в ы з ов а м етод ов ис пол ь з ует с я инс т рукция в ид а ИмяОбъекта.ИмяМетода(Параметры);
которая с од ержат ел ь но(ноне с инт акс ичес ки!) э кв ив ал ент на в ы ражению ИмяМетода(ИмяОбъекта,Параметры); 2
Ч ит ател ь, в ероятно, уже з ам ет ил , чтотерм ин «объект » ис пол ь з ует с я нам и в д вух нес кол ь ко раз л ичны хс м ы с л ах: перем енная кл ас с ов ого типа и обл ас ть пам яти, ад рес уем ая этой перем енной. Второе бол ее точно, од накос точки з рения объектной ид еол огии конкрет ное пред с т ав л ение объект а не им еет з начения, поэтом у перв ая инт ерпрет ация т акже д опус т им а. Дал ее, гов оря о перем енной x как об объект е, м ы в с егд а буд ем под раз ум ев ать объект, ад рес которогос од ержит x.
19
Т аким образ ом , перв ы й аргум ент прос тос т ав ит с я перед им енем под програм м ы и отд ел яет с я от неготочкой. От с юд а с л ед ует, в час т нос т и, чтокажд ом у м етод у перед ает с я по крайней м ере од ин аргум ент — объект, д л я которогоэ тот м етод в ы з ы в ает с я. Данное прав ил о в пол не с оот в ет с т в ует поним анию м етод а как с в ойс т в а объект а: нел ь з я гов орит ь ос в ойс т в е, не указ ав , к чем у им енно оно от нос ит с я. Ст анов ит с я яс но т акже, почем у в рас с м от ренном в ы ш е прим ере м етод ы Square и Perimeter объяв л ены без парам ет ров : необход им ая информ ация буд ет перед ана им ав том ат ичес ки. Н ов ая, не с ов с ем обы чная, форм а з апис и в д ейс т в ит ел ь нос т и поз в ол яет нес кол ь кос ократ ит ь кол ичес т в оис пол ь з уем ы хс кобок, ув ел ичив ая т ем с ам ы м чит абел ь нос т ь в ы ражений. В с ам ом д ел е, ес л и эл ем ент д анны х, в оз в ращаем ы й м етод ом -функцией, в с в ою очеред ь яв л яет с я объектом , тод л я негос нов а м огут бы т ь в ы з в аны с оот в ет с т в ующие м етод ы . В рез ул ьт ат е, в оз никают пос л ед ов ат ел ь нос т и в ид а Объект.Метод1(¼).Метод2(¼).Метод3(¼).¼
гд е м етод с ном ером k от нос ит с я к кл ас с у, котором у принад л ежит объект, в оз в ращаем ы й м етод ом с ном ером k - 1.
Рас с м от рим , наконец, небол ь ш ую програм м у, д ем онс т рирующую работ у с объект ам и кл ас с а Triangle. Сам а в оз м ожнос т ь прив ес т и т акой прим ер уже с ейчас показ ы в ает, чтод л я ис пол ь з ов ания кл ас с а д ос т аточнол иш ь им ет ь пред с т ав л ение оегоинт ерфейс е и с ов ерш енноне обяз ат ел ь ноз нат ь , как им еннореал из уют с я м етод ы . Пример 2.2. И с пол ь з ов ание кл ас с а Triangle. program TestTriangle; {$APPTYPE CONSOLE} uses UnitTriangle;
// подключаем модуль, в котором // определен класс Triangle // объявление объектных переменных
var t1, t2: Triangle; begin t1:=Triangle.Create; // объекты размещаются в памяти и их адреса t2:=Triangle.Create; // присваиваются объектным ссылкам t1.a:=2; t2.a:=3; // полям объектов приписываются t1.b:=3; t2.b:=4; // конкретные числовые значения t1.c:=4; t2.c:=5; // WriteLn('Square of triangle 1: ', t1.Square); WriteLn('Perimeter of triangle 1: ', t1.Perimeter); WriteLn('Square of triangle 2: ', t2.Square); WriteLn('Perimeter of triangle 2: ', t2.Perimeter);
20
{ Для объектов t1 и t2 вызываются методы Square и Perimeter. Возвращаемые ими действительные значения выводятся на экран. } t1.Destroy; t2.Destroy; ReadLn; end.
// объекты удаляются из памяти
Прив ед енны й код с од ержит од ну нов ую операцию: уд ал ение объект а из пам ят и. Вообще, тот факт, что объект ная перем енная пред с т ав л яет с обой указ ат ел ь , с л ед ует в с е в рем я учит ы в ат ь при раз работ ке програм м ы . Впрочем , пробл ем ы , которы е з д ес ь в оз никают, характ ерны д л я л юбы хд инам ичес кихперем енны х. Прежд е в с его необход им о в ним ат ел ь но с л ед ит ь з а т ем , чтобы объект ной перем енной в с егд а бы л с опос т ав л ен ад рес с ущес т в ующего объект а. Попы т ка обращения к пол ю ил и м етод у объект а пос ред с т в ом перем енной, не с од ержащей реал ь ногоад рес а, не д иагнос т ирует с я ком пил ятором и, как прав ил о, в ы з ы в ает ош ибку (ис кл ючит ел ь ную с ит уацию кл ас с а Access violation — наруш ение д ос т упа) в ов рем я в ы пол нения програм м ы . Пос кол ь ку объект ы раз м ещают с я в пам ят и програм м ис том , он же д ол жен поз абот ит ь с я и об их с в оев рем енном уд ал ении. Дл я э того ис пол ь з ует с я инс т рукция ИмяОбъекта.Destroy;
Св ои ос обеннос т и им еют и операции над объект ам и. Т ак, прис в аив ание a:=b, гд е a и b — некоторы е объект ны е перем енны е, в л ечет з а с обой не копиров ание з начений пол ей, а с ов м ещение указ ат ел ей: пос л е нее обе перем енны е указ ы в ают на од ну и т у же обл ас т ь пам ят и. Е с л и д о э тогоперем енная a уже с од ержал а ад рес некоторой с т рукт уры , тот еперь д ос т уп к ней пол учит ь с корее в с егоне уд ас т с я. Соот в ет с т в ующую ос обеннос т ь им еет и с рав нение д в ухобъектов . Е с л и перем енны е a и b с од ержат раз л ичны е ад рес а, торез ул ьт атом операции a=b буд ет «л ожь » д аже в том с л учае, когд а э т и объект ы принад л ежат од ном у кл ас с у и ихпол я им еют од инаков ы е з начения. Н аконец, при ис пол ь з ов ании объект а в качес т в е парам ет ра под програм м ы , пос л ед ней перед ает с я его реал ь ны й ад рес . Т аким образ ом , появ л яет с я не в с егд а жел ат ел ь ная в оз м ожнос т ь м од ифициров ат ь д анны й объект в процес с е ее в ы пол нения. Объяв л ение парам ет ра как конс т ант ного(ис пол ь з ов ание префикс а const) не реш ает э т у пробл ем у.
21
2.3. Реализац иякласса Реал из ация кл ас с а пред с т ав л яет с обой набор опред ел ений в с ех егом етод ов . В Object Pascal в с е опред ел ения д ол жны наход ит ь с я з а пред ел ам и инт ерфейс а кл ас с а и не пред ш ес т в ов ат ь ем у. Б ол ее того, ес л и инт ерфейс , буд учи объяв л ением т ипа д анны х, м ожет рас пол агат ь с я как в раз д ел е инт ерфейс а м од ул я, т ак и в раз д ел е реал из ации, то реал из ация кл ас с а — тол ь ков раз д ел е реал из ации м од ул я. Синт акс ичес ки опред ел ения м етод ов отл ичают с я от опред ел ений обы чны хпод програм м л иш ь т ем , чтоихид ент ификаторам пред ш ес т в ует им я кл ас с а, от д ел яем ое т очкой (гов орят, чтоим я м ет од а ква л ифицируе тся им енем кл ас с а). Пос л ед ов ат ел ь нос т ь , в которой они прив од ят с я, не обяз ана в точнос т и пов торят ь пос л ед ов ат ел ь нос т ь объяв л ений в инт ерфейс е кл ас с а. Как уже бы л оот м еченов пред ы д ущем параграфе, кажд ом у м етод у, пом им о перечис л енны х в его объяв л ении парам ет ров , перед ает с я еще од ин — объект, д л я которого д анны й м етод в ы з в ан. Обрат ит ь с я к э том у объект у в нут ри реал из ации м етод а м ожно по им ени self (с ам ). Т аким образ ом , д л я работ ы с пол ям и и м етод ам и т екущегообъект а прим еняют с я в ы ражения в ид а self.ИмяПоля
и self.ИмяМетода(Параметры)
Пример 2.3. Реал из ация м етод ов кл ас с а Triangle. function Triangle.Perimeter: Real; begin result:=self.a+self.b+self.c; // возвращается сумма значений // полей текущего объекта end; function Triangle.Square: Real; var p:Real; begin p:=self.Perimeter/2; result:=Sqrt(p*(p-self.a)*(p-self.b)*(p-self.c)); { Площадь рассчитывается по формуле Герона. Для вычисления полупериметра используется предыдущий метод, вызываемый для объекта self. } end;
22
Рас с м от рим т еперь под робнее, как работ ает програм м а из прим ера 2.2. Ст рока WriteLn('Square of triangle 1: ', t1.Square);
прив од ит к в ы з ов у м етод а Square д л я объект а t1. В качес т в е парам ет ра ем у перед ает с я ад рес , которы й хранит перем енная t1. Сл ед ующей в ы пол няет с я перв ая с т рока из реал из ации м етод а Square: p:=self.Perimeter/2;
Зд ес ь тот же с ам ы й объект уже ад рес ует указ ател ь self. Т аким образ ом , м етод Perimeter с нов а в ы з ы в ает с я д л я объект а t1 и под с чит ы в ает с ум м у егопол ей. Дал ее ис пол нение в оз в ращает с я в м етод Square, з ав ерш ающий в ы чис л ение пл ощад и т реугол ь ника t1, и з ат ем в ос нов ную програм м у. Дв ум я с т рокам и ниже в ы з ов под програм м ы Square произ в од ит с я уже д л я объект а t2, поэ том у им енноегоад рес буд ут с од ержат ь указ ат ел и self в ход е в ы пол нения м етод ов Square и Perimeter и, с л ед ов ат ел ь но, им енноегопол я буд ут учас т в ов ат ь в в ы чис л ениях. Сл ед ует от м ет ит ь , что ис пол ь з ов ание указ ат ел я self не яв л яет с я обяз ат ел ь ны м : к пол ям и м етод ам т екущего объект а м ожно обращат ь с я прос то по ихим енам . М ы , од нако, не буд ем пока ис пол ь з ов ат ь эт у в оз м ожнос т ь .
2.4. О б ласти видимо сти членов класса Ос обеннос т и кл ас с ов , опис анны е д о с их пор, не д ают ничего принципиал ь но нов ого по с рав нению с м од ул ям и. Е д инс т в енны м з ам ет ны м отл ичием яв л яет с я бол ее чет кое опред ел ение перечня под програм м , которы е м ожноприм енит ь к з ад анном у т ипу. Э т а в оз м ожнос т ь , од нако, м ал ос пос обс т в ует д ос т ижению наш ей ос нов ной цел и — с оз д анию абс т ракт ны хт ипов , не поз в ол яющихпол ь з ов ат ел ю в ид ет ь д ет ал и с в оей реал из ации. Дл я реш ения д анной з ад ачи прим еняет с я с пециал ь ны й м еханиз м ограничения д ос т упа к чл енам кл ас с а — з ад ание ихобл а сте й видимости. В Object Pascal объяв л ению л юбого чл ена в инт ерфейс е кл ас с а м ожет пред ш ес т в ов ат ь од ноиз з арез ерв иров анны хс л ов : private (за крытый), protected (за щищ е н н ый), public (открытый), а т акже published (опубл икова н н ый) и automated (а втома тизирова н н ый), опред ел яющее егов ид им ос т ь . Е с л и не указ анони од ноиз них, точл ен им еет т у же обл ас т ь в ид им ос т и, чтои пред ш ес т в ующий ем у. Э топоз в ол яет объед инят ь 23
чл ены в группы , обл ад ающие од ним и т ем же уров нем д ос т упа, указ ы в ая егоод ин раз : ИмяКласса = class private { объявления закрытых членов } protected { объявления защищенных членов } public { объявления открытых членов } published { объявления опубликованных членов } automated { объявления автоматизированных членов } end;
Ч л ены , объяв л ения которы храс пол ожены в с ам ом начал е инт ерфейс а кл ас с а д оперв огояв ногоуказ ания обл ас т и в ид им ос т и, с чит ают с я опубл иков анны м и (ес л и програм м а ком пил ирует с я в с ос тоянии {$M+}) ил и от кры т ы м и (в с ос тоянии {$M-}). Закры т ы е чл ены кл ас с а в ид ны л иш ь в пред ел ах того м од ул я, в котором э тот кл ас с опред ел ен, от кры т ы е — в с юд у, гд е в ид ен с ам кл ас с . Защищенны е чл ены , пом им ом од ул я, с од ержащегоопред ел ение кл ас с а, д ос т упны т акже при реал из ации м етод ов т ехкл ас с ов , которы е яв л яют с я нас л ед никам и д анного (м еханиз м нас л ед ов ания буд ет под робно рас с м ат рив ат ь с я в § 3.1). Опубл иков анны е и ав т ом ат из иров анны е чл ены им еют т у же в ид им ос т ь , чтои от кры т ы е. И хотл ичия с в яз аны с в оз м ожнос тям и Delphi, которы е с ейчас не яв л яют с я д л я нас с ущес т в енны м и. Т аким образ ом , кл ас с ы пред ос т ав л яют т е же ос нов ны е уров ни д ос т упа, чтои м од ул и: от кры т ы й и з акры т ы й, од накос пос об ихз ад ания яв л яет с я з начит ел ь но бол ее гибким . При ис пол ь з ов ании т рад иционны х с л ожны х т ипов д анны х, в ид им ос т ь ихв нут ренней с т рукт уры цел иком опред ел яет с я в ид им ос т ь ю с ам ого т ипа. Кл ас с ы же поз в ол яют пол нос т ь ю с кры т ь от пол ь з ов ат ел я с в ое пред с т ав л ение, объяв ив в с е пол я з акры т ы м и, и при э том не ограничив ат ь его д ос т уп с обс т в енно к т ипу д анны х, пред ос т ав л яя т ем с ам ы м в оз м ожнос т ь с оз д ания с оот в ет с т в ующихперем енны х. Прив ед ем т еперь нов ую в ерс ию библ иот еки д л я работ ы с рационал ь ны м и чис л ам и, с в обод ную (почт и) от нед ос т ат ков , перечис л енны хв начал е § 2.1. Она буд ет с од ержат ь опред ел ение ед инс т в енного кл ас с а: Rational, и перв ое, что необход им о с д ел ат ь , — э то раз работ ат ь инт ерфейс д анногокл ас с а. 24
Пример 2.4. И нт ерфейс кл ас с а Rational. Rational = class // рациональное число private // закрытые члены класса num: Integer; den: Integer; protected // защищенные члены класса procedure Normalize; procedure Reduce; public // открытые члены класса function GetNum: Integer; function GetDen: Integer; procedure SetNum(value:Integer); procedure SetDen(value:Integer); function Plus(r:Rational): Rational; function Minus(r:Rational): Rational; function Dot(r:Rational): Rational; function Slash(r:Rational): Rational; procedure Add(r:Rational); procedure Subtract(r:Rational); procedure MultiplyBy(r:Rational); procedure DivideBy(r:Rational); end;
// числитель // знаменатель // Нормализовать // Сократить // // // // // // // // // // // //
Вернуть значение поля num Вернуть значение поля den Установить значение num Установить значение den Плюс Минус Точка Косая черта Прибавить Вычесть УмножитьНа РазделитьНа
И т ак, кл ас с Rational факт ичес ки объед инил в с ебе в с е чл ены м од ул я из § 1.1. При э том кол ичес т в опарам ет ров под програм м ум ень ш ил ос ь на ед иницу: перв ы й аргум ент т еперь перед ает с я им ав том ат ичес ки. Пол ученны е в рез ул ь т ат е объяв л ения бинарны хопераций в ы гл яд ят нес кол ь кос т ранно, од нако в програм м е ихв ы з ов буд ет им ет ь бол ее ес т ес т в енны й в ид . В с оотв ет с т в ии с общей ид еей с окры т ия реал из ации пол я кл ас с а объяв л ены з акры ты м и, а операции, которы е м ожно в ы пол нять над его объект ам и — от кры ты м и. Обл ас ть в ид им ос ти процед ур Normalize и Reduce нес кол ь коув ел ичена пос рав нению с пред ы д ущей в ерс ией. См ы с л д анногореш енияс т анет понятен тол ь копос л е из учения нас л ед ов анияв § 3.1. Ограничение д ос т упа к пол ям num и den прив ел о к том у, что пол ь з ов ат ел ь пот ерял в оз м ожнос т ь прис в аив ат ь объект ам кл ас с а Rational конкрет ны е з начения и уз нав ат ь рез ул ьт ат в ы пол нения операций. Дл я ком пенс ации э тогоэ ффект а в инт ерфейс кл ас с а д обав л ены м етод ы Get¼ и Set¼ Н ес м от ря на то, чтоуказ анны е м етод ы пред пол агает с я ис пол ь з ов ат ь д л я непос ред с т в енного обращения к пол ям , д анны й ш аг почт и не ум ень ш ает абс т ракт нос т и т ипа.
25
В с ам ом д ел е, л юбое рационал ь ное чис л оим еет цел ы е чис л ит ел ь и з нам енат ел ь , и необход им ос т ь хранит ь ихим еннов д в ухпол яхт ипа Integer никак не с л ед ует из объяв л ений нов ы хм етод ов . Од накояв ное указ ание с кал ярного (прос того) т ипа д л я парам ет ров и в оз в ращаем ы хз начений эт их под програм м ограничив ает д иапаз он д опус т им ы х з начений чис л ит ел я и з нам енат ел я. Б ол ее прав ил ь ны м бы л о бы опред ел ит ь с в ой кл ас с и д л я пред с т ав л ения цел ы хчис ел , нотогд а с оот в ет с т в ующие пробл ем ы в оз никл и бы уже д л я него. В д ейс т в ит ел ь нос т и, ед инс т в енны м реш ением , поз в ол яющим с оз д ав ат ь ис т инноабс т ракт ны е т ипы , яв л яет с я пол ны й от каз от ис пол ь з ов ания с кал ярны хт ипов д анны х. Яз ы ки, реал из ующие д анны й под ход , тоес т ь яв л яющиес я чис тообъект но-ориент иров анны м и, с ущес т в уют, од наков с е они проигры в ают яз ы кам с ос м еш анной м од ел ь ю в пл ане бы с т род ейс т в ия.
Зав ерш им т еперь раз работ ку библ иот еки, реал из ов ав м етод ы кл ас с а Rational. Пример 2.5. Опред ел ение м од ул я, с од ержащегокл ас с Rational. unit UnitRational; interface type Rational = class ... // здесь располагается интерфейс класса, приведенный выше end; implementation uses SysUtils; // модуль включает поддержку исключений function Rational.GetNum: Integer; begin result:=self.num; end; function Rational.GetDen: Integer; begin result:=self.den; end; procedure Rational.SetNum(value:Integer); begin self.num:=value; end; procedure Rational.SetDen(value:Integer); begin if value>0 then // знаменатель всегда должен быть положителен self.den:=value else // иначе возбуждается исключение с сообщением // "Недопустимое значение знаменателя"
26
raise Exception.Create('Illegal value of denominator'); end; procedure Rational.Normalize; begin if self.den=b then a:=a-b else b:=b-a; self.num:=self.num div b; self.den:=self.den div b; end; procedure Rational.DivideBy(r:Rational); var _num,_den:Integer; begin if r.num=0 then raise Exception.Create('Division by zero'); _num:=self.num*r.den; _den:=self.den*r.num; self.num:=_num; self.den:=_den; self.Normalize; self.Reduce; end; function Rational.Slash(r:Rational): Rational; var res:Rational; begin if r.num=0 then raise Exception.Create('Division by zero'); res:=Rational.Create; // переменная res размещается в памяти res.num:=self.num*r.den; // теперь возможны res.den:=self.den*r.num; // обращения к ее полям res.Normalize; res.Reduce; // и методам result:=res; // адрес res возвращается в качестве значения функции end; { Удалять переменную res при выходе из функции нельзя, так как она содержит результат вычисления. } ... // реализация остальных методов производится аналогично end.
27
Опред ел ения м етод ов GetNum, GetDen и SetNum очев ид ны . Процед ура SetDen прежд е, чем ис пол ь з ов ат ь з начение, перед анное ей в качес т в е парам ет ра, пров еряет, уд ов л ет в оряет л и оноус л ов ию норм ал из ации. Е с л и нет — в оз бужд ает с я ис кл ючение. Пос кол ь ку в с е под програм м ы наход ят с я в м од ул е, с од ержащем опред ел ение кл ас с а, в с юд у д опус кает с я прям ое обращение к пол ям , нев з ирая на ихобл ат ь в ид им ос т и. Реал из ация процед ур Normalize, Reduce и DivideBy отл ичает с я от бол ее ранней в ерс ии тол ь ко з ам еной им ени перв ого парам ет ра на self. То, чтом ы им еем д ел ос объект ам и, а не с з апис ям и, прояв л яет с я л иш ь в реал из ации м етод а Slash. Т ип з начения э той функции опред ел ен как Rational, с л ед ов ат ел ь но она д ол жна в оз в ращат ь ад рес некоторого объект а наш его кл ас с а. Раз м ещение д анногообъект а в пам ят и произ в од ит инс т рукция res:=Rational.Create;
Тол ь ко пос л е э того с т анов ит с я в оз м ожной инициал из ация его пол ей и д ругие операции. Сл ед ует обрат ит ь ос обое в ним ание на то, чтоуд ал ят ь объект res поз ав ерш ении работ ы функции нел ь з я: он хранит рез ул ьт ат ы в ы чис л ений и д ол жен бы т ь перед ан в ы з ы в ающей програм м е. Пос л ед няя и д ол жна поз абот ит ь с я об ос в обожд ении пам ят и. В з акл ючение рас с м от рим прил ожение, д ем онс т рирующее работ у с объект ам и кл ас с а Rational и пред с т ав л яющее с обой прос тую м од ификацию програм м ы из § 1.2. Пример 2.6. Дем онс т рация операций, в ы пол няем ы хнад объект ам и кл ас с а Rational. program TestRational; {$APPTYPE CONSOLE} uses UnitRational; // подключаем модуль с определением класса var r1,r2,ra,rs,rm,rd: Rational; begin r1:=Rational.Create; // переменные r1 и r2 размещаются в памяти r2:=Rational.Create; // r1.SetNum(1); r1.SetDen(2); // переменным r1 и r2 присваиваются r2.SetNum(2); r2.SetDen(6); // значения 1/2 и 2/6 ra:=r1.Plus(r2); rs:=r1.Minus(r2); rm:=r1.Dot(r2); rd:=r1.Slash(r2); { Для объекта r1 вызываются методы-функции с адресом объекта r2 в качестве параметра. Возвращаемые ими ссылки на объекты,
28
содержащие результаты вычислений, присваиваются заранее объявленным, но не инициализированным переменным ra, rs, rm и rd. } WriteLn('Plus: ',ra.GetNum,'/',ra.GetDen); WriteLn('Minus: ',rs.GetNum,'/',rs.GetDen); WriteLn('Dot: ',rm.GetNum,'/',rm.GetDen); WriteLn('Slash: ',rd.GetNum,'/',rd.GetDen); ra.Add(r2); // rs.Subtract(r2); // теперь к объектам, созданным ранее, rm.MultiplyBy(r2); // применяются операторы с присвоением rd.DivideBy(r2); // WriteLn('Add: ',ra.GetNum,'/',ra.GetDen); WriteLn('Sub: ',rs.GetNum,'/',rs.GetDen); WriteLn('Mul: ',rm.GetNum,'/',rm.GetDen); WriteLn('Div: ',rd.GetNum,'/',rd.GetDen); r1.Destroy; r2.Destroy; { Функции Plus, Minus, Dot и Slash возвращают указатель на уже созданный объект, поэтому заранее размещать в памяти переменные ra, rs, rm и rd не требовалось. Однако уничтожить их по завершении программы необходимо. } ra.Destroy; rs.Destroy; rm.Destroy; rd.Destroy; ReadLn; end.
Зам ет им , чтов э той програм м е, в отл ичие от прив ед енной в § 1.2, непос ред с т в енное обращение к пол ям перем енны хуже нев оз м ожно, поэ том у в с юд у ис пол ь з уют с я в ы з ов ы м етод ов Get¼ и Set¼ Другим в ажны м отл ичием яв л яет с я яв ное с оз д ание и уд ал ение объектов , в том чис л е и т ех, которы е появ ил ис ь в процес с е работ ы под програм м м од ул я. Вообще, при работ е с функциям и, в оз в ращающим и с с ы л ки на объект ы , очень л егко д опус т ит ь ут ечку пам ят и. Рас с м от рим в качес т в е прим ера инс т рукцию sum:=r1.Plus(r2).Plus(r3);
гд е r1, r2, r3 и sum — объект ны е перем енны е кл ас с а Rational, причем r1, r2 и r3 уже с од ержат ад рес а реал ь ны хобъектов . И с пол ь з ов ание д анного в ы ражения не тол ь ко не яв л яет с я пред ос уд ит ел ь ны м , нод аже наоборот, поощряет с я объект ны м с инт акс ис ом . К объект у r1 прим еняет с я м етод Plus с парам ет ром r2, в оз в ращающий с с ы л ку на нов ы й объект кл ас с а Rational (наз ов ем егоtemp), с од ержащий с ум м у чис ел r1 и r2. Зат ем к объект у temp с нов а прим еняет с я м етод Plus с парам ет ром r3. Рез ул ьт атом егов ы пол нения яв л яет с я с с ы л ка еще на од ин объект в с е того же кл ас с а, которая и прис в аив ает с я перем енной sum.
29
Т ребуем ая операция произ в ед ена: sum ад рес ует объект, пред с т ав л яющий с обой с ум м у чис ел r1, r2 и r3. Н очтопроиз ош л ос объектом temp? Н ичего. Он по-прежнем у с ущес т в ует гд е-тов пам ят и, ноад рес егопот ерян. Т аким образ ом , програм м ис т в ы нужд ен в ы бират ь : л ибо не ис пол ь з ов ат ь с ов ерш енноес т ес т в енны е с цепки операторов , л ибом ирит ь с я с пос тоянной ут ечкой пам ят и. Н екоторы м ком пром ис с ом м ожет с л ужит ь м од ифициров анная в ерс ия оператора с прис в оением , пред с т ав л яющая с обой функцию, в оз в ращающую ад рес л ев огооперанд а: function Rational.Add(r:Rational): Rational; var _num,_den:Integer; begin _num:=self.num*r.den; _den:=self.den*r.num; self.num:=_num; self.den:=_den; self.Normalize; self.Reduce; result:=self; // в качестве результата возвращается // текущий объект end;
В этом с л учае в м ес то прив ед енной в ы ш е инс т рукции м ожно ис пол ь з ов ат ь в ы ражение sum.Add(r1).Add(r2).Add(r3);
пос л ед ов ат ел ь нод обав л яющее чис л а r1, r2 и r3 к sum. Зд ес ь , од нако, объект sum д ол жен бы т ь з аранее раз м ещен в пам ят и и инициал из иров ан нул ем , чтот акже не ув ел ичив ает чит абел ь нос т и програм м ы . Пос л е в с егос каз анногоу чит ат ел я м ожет с л ожит ь с я в печатл ение, что ут ечка пам ят и яв л яет с я неот ъем л ем ой чертой объект ного програм м иров ания. Э тоне т ак: с ущес т в уют ал горит м ы , поз в ол яющие ав том ат ичес ки уд ал ят ь объект ы , в которы хбол ь ш е нет необход им ос т и (этот процес с наз ы в ает с я «с боркой м ус ора» ). Под обны й ал горит м реал из ов ан, наприм ер, в яз ы ке Java.
2.5. К о нструкто ры и деструкто ры Н аряд у с опис анны м и в ы ш е с пос обам и д л я с оз д ания и уничтожения объектов м огут ис пол ь з ов ат ь с я с пециал ь ны е м етод ы : кон структоры и де структоры. Синт акс ичес ки они опред ел яют с я т ак же, как и обы чны е м етод ы -процед уры , тол ь коз арез ерв иров анное с л ов оprocedure з ам еняет с я на constructor ил и destructor. В час т нос т и, конс т рукторы и д ес т рукторы м огут им ет ь л юбой набор форм ал ь ны хпарам ет ров . Кром е в ы д ел ения и ос в обожд ения пам ят и, з аним аем ой объектом , 30
конс т рукторы и д ес т рукторы в ы пол няют т е же функции, что и с екции инициал из ации и финал из ации м од ул я. Конс т руктор з ад ает начал ь ны е з начения пол ей объект а и раз м ещает в пам ят и д инам ичес кие с т рукт уры д анны х. Дес т руктор ос в обожд ает рес урс ы , з анят ы е объектом в о в рем я егос ущес т в ов ания. Н ес м от ря на в неш ний в ид опред ел ения, конс т руктор в с егд а в оз в ращает ад рес с оз д анногоим объект а. Поэ том у д л я его в ы з ов а обы чно ис пол ь з ует с я в ы ражение ИмяОбъекта := ИмяКласса.ИмяКонструктора(Параметры);
Прив ед енная в ы ш е инс т рукция ИмяОбъекта := ИмяКласса.Create;
в д ейс т в ит ел ь нос т и яв л яет с я час т ны м с л учаем э того в ы ражения. Она раз м ещает объект пос ред с т в ом унас л ед ов анногоконс т руктора Create (о нас л ед уем ы хм етод ахс м . § 3.1). Вм ес т е с т ем , конс т руктор м ожет бы т ь в ы з в ан и при пом ощи обы чной объект ной с с ы л ки: ИмяОбъекта.ИмяКонструктора(Параметры);
В э том с л учае он не с оз д ает нов ы й объект, а оперирует с ущес т в ующим , в ы пол няя л иш ь т е инс т рукции, которы е перечис л ены в его(конс т руктора) реал из ации, и в оз в ращает ад рес указ анногообъект а. Вы з ов д ес т руктора ничем не отл ичает с я от в ы з ов а обы чногом етод а-процед уры : ИмяОбъекта.ИмяДеструктора(Параметры);
Как и в ы ш е, Destroy яв л яет с я прос тоим енем д ес т руктора, нас л ед уем ого кажд ы м кл ас с ом . Уничтожение объект а ид ет в поряд ке, обрат ном с оз д анию: с начал а в ы пол няют с я инс т рукции из реал из ации д ес т руктора, з ат ем ос в обожд ает с я пам ят ь , з аним аем аяобъект ом . Пос кол ь ку объект ы рас с м от ренного нам и кл ас с а Rational не ис пол ь з уют никакихраз д ел яем ы хрес урс ов , ос обы е д ес т рукторы д л я них не т ребуют с я. А в от хотя бы од ин с пециал ь ны й конс т руктор, наоборот, необход им , т ак как при с оз д ании нов огообъект а егоз нам енат ел ь с раз у хот ел ос ь бы ус т анав л ив ат ь бол ь ш им 0. Добав им к с екции public инт ерфейс а кл ас с а Rational объяв л ения constructor CreateNumber; constructor CreateAs(n, m: Integer);
а в раз д ел реал из ации м од ул я UnitRational с л ед ующий код : 31
constructor Rational.CreateNumber; begin self.num:=0; self.den:=1; end; constructor Rational.CreateAs(n, m: Integer); begin self.SetNum(n); self.SetDen(m); end;
Т еперь при ис пол ь з ов ании в ы ражения r := Rational.CreateNumber;
перем енная r пол учит ад рес объект а, пол я которого уже с од ержат коррект ны е в ел ичины 0 и 1. Е с л и же с оз д ать объект при пом ощи инс т рукции r := Rational.CreateAs(a, b);
тод л я инициал из ации чис л ит ел я и з нам енат ел я буд ут ис пол ь з ов аны м етод ы SetNum и SetDen, т ак чточис л оr окажет с я рав ны м a/b, л иш ь ес л и в ы ражения a и b им еют д опус т им ы е з начения. Кром е того, в ы з ы в ая конс т рукторы д л я уже с ущес т в ующегообъект а r: r.CreateNumber; r.CreateAs(a, b);
м ожнол егкос брос ит ь егоз начение в 0 ил и из м енит ь на т ребуем ое. Н екоторы м чит ат ел ям , в ероят но, покажет с я с т ранны м , что м ы прид ум ы в аем в с е нов ы е им ена д л я конс т рукторов в м ес то того, чтобы в ос пол ь з ов ат ь с я в ес ь м а ум ес т ной з д ес ь перегруз кой ил и ус т анов ит ь д л я парам ет ров n и m з начения поум ол чанию. Сд ел аноэтонам ереннос цел ь ю м акс им ал ь ноупрос т ит ь м ат ериал .
К с ожал ению, в нов ь д обав л енны е м етод ы не поз в ол яют реш ит ь в с ехпробл ем : пол ь з ов ат ел ь по-прежнем у м ожет с оз д ат ь нов ы й объект пос ред с т в ом обы чного конс т рукт ора Create, которы й не гарант ирует коррект нос т и его з начения. Ч т обы л икв ид иров ат ь т акую в оз м ожнос т ь , с л ед ует не прос то д обав ит ь к кл ас с у нов ы е конс т рукт оры , а переопред ел ит ь уже с ущес т в ующий. В д ейс т в ит ел ь нос т и э тоочень л егко: д ос т аточно л иш ь из м енит ь им я CreateNumber на Create, чт о м ы и с д ел аем , ус т ранив т ем с ам ы м пос л ед ний из нед ос т ат ков библ иот еки, перечис л енны хв начал е § 2.1. 32
Под робном еханиз м переопред ел ения м етод ов рас с м ат рив ает с я в с л ед ующем параграфе. У п раж нения 2.1. Доопред ел ит е кл ас с Rational, в кл ючив в негооператоры прис в аив ания и с рав нения. 2.2. Вз яв з а ос нов у библ иот еку из з ад ачи 1.1, опред ел ит е кл ас с д л я пред с т ав л ения в екторов д л ины n с цел ы м и ком понент ам и. Реал из уйт е операторы с л ожения, с кал ярного произ в ед ения, прис в аив ания, с рав нения на рав енс т в о, м етод ы д л я в ы чис л ения д л ины , чт ения и з апис и з начений ком понент. Н апиш ит е програм м у, д ем онс т рирующую работ у с объект ам и д анногокл ас с а. 2.3. Т а же з ад ача, но д л я м ат риц раз м ера n ´ n, эл ем ент ам и которы хяв л яют с я рационал ь ны е чис л а, т. е. объект ы рас с м от ренногокл ас с а Rational. Н еобход им ы е м ет од ы : с л ожение, ум ножение, прис в аив ание, с рав нение на рав енс т в о. У казание. Данном у кл ас с у необход им ы с пециал ь ны е конс т руктор и д ес т руктор. Перв ы й т ребует с я д л я раз м ещения в пам ят и объектов кл ас с а Rational, в торой — д л я ихуд ал ения. Обрат ит е т акже в ним ание на то, что м етод ы чт ения-з апис и эл ем ентов д ол жны копиров ат ь их з начения, а не ад рес а. В прот ив ном с л учае у пол ь з ов ат ел я появ л яет с я в оз м ожнос т ь неяв ногоиз м енения с од ержим огом ат рицы .
33
3. О Б ЪЕ К Т Н О -О РИ Е Н Т И РО В А Н Н О Е ПРО Г РА М М И РО В А Н И Е 3.1. Н аследование Как с л ожит ь д в е м ат рицы ? Дл я м ат ем ат ика от в ет на э т от в опрос очев ид ен: поэл ем ент но. Програм м ис т же, ис пол ь з ующий яз ы к с о с т рогой т ипиз ацией, в ы нужд ен с начал а уточнит ь , какой т ип им еют эл ем ент ы м ат риц. В с ам ом д ел е, при т рад иционном под ход е неяв ны е (ав том ат ичес кие) преобраз ов ания т ипов ограничив ают с я обы чно операциям и над с кал ярам и и некоторы м и прос т ейш им и прив ед ениям и. Поэ том у раз работ ат ь под програм м у, приним ающую в качес т в е аргум ентов м ат рицы раз л ичной природ ы , оказ ы в ает с я в ес ь м а з ат руд нит ел ь но. Как прав ил о, д л я кажд ой пары т ипов д анны хприход ит с я с оз д ав ат ь отд ел ь ную функцию, с нов а и с нов а пов торяя пос ут и од ин и тот же ал горит м . Н ет руд но в ид ет ь , что з ав ис им ос т ь кол ичес т в а под програм м от чис л а ис пол ь з уем ы хт ипов оказ ы в ает с я д л я бинарной операции д аже не л инейной, а кв ад рат ичной. Как с л ед с т в ие, програм м ис т (а без прим енения перегруз ки и пол ь з ов ат ел ь ) очень с короначинает тонут ь в э том м ногообраз ии. Кром е того, кл иент ы в ы нужд ены под д ержив ат ь пос тоянную обрат ную с в яз ь с раз работ чиком библ иот еки, пос кол ь ку они не в с егд а м огут ис пол ь з ов ат ь уже им еющиес я ал горит м ы д л я работ ы с нов ы м и, необход им ы м и им т ипам и д анны х. Объект но-ориент иров анны е яз ы ки пред ос т ав л яют в рас поряжение програм м ис т а с ред с т в а, поз в ол яющие д ос т аточно л егко раз рабат ы в ат ь обобщенны е ал горит м ы , прим еним ы е (причем без переком пил яции) к пот енциал ь но бес конечном у м ножес т в у раз л ичны хт ипов . Раз ум еет с я, э тот э ффект не м ожет бы т ь д ос т игнут без некоторого ос л абл ения конт рол я т ипов с ос тороны ком пил ятора, и в ел ичина т акогоос л абл ения оказ ы в ает с я очень в ажной характ ерис т икой яз ы ка. Од ной из нов ы хформ опред ел ения от нош ений м ежд у т ипам и, с очет ающей преим ущес т в а обоихпод ход ов , яв л яет с я раз работ ка ие ра рхии н а сл едова н ия. На сл едова н ием наз ы в ает с я м еханиз м , при котором од ин кл ас с опред ел яет с я на ос нов е д ругого, уже с ущес т в ующего. Ст ары й кл ас с наз ы в ают предком ил и ба зовым кл а ссом, нов ы й — потомком ил и производн ым кл а ссом. При од иночном нас л ед ов ании кажд ы й кл ас с им еет не бол ее од ного пред ка, поэ том у с ов окупнос т ь в с ех кл ас с ов и от нош ений м ежд у ним и образ ует д рев ов ид ную с т рукт уру, наз ы в аем ую иерархией нас л ед ов ания. 34
Е с т ес т в енно, баз ов ы й кл ас с в ы бирает с я не с л учайно, а т ак, чтобы кл ас с -потом ок с с од ержат ел ь ной точки з рения пред с т ав л ял с обой его под т ип. Т аким образ ом , от нош ение тожд ес т в а т ипов , ис пол ь з уем ое при т рад иционном под ход е д л я пров ерки коррект нос т и прис в аив ания, з ам еняет с я бол ее с л абы м от нош ением в кл ючения. Под робнее ос ов м ес т им ос т и кл ас с ов м ы буд ем гов орит ь в § 3.2. В процес с е нас л ед ов ания в с е чл ены баз ов огокл ас с а ав том ат ичес ки с т анов ят с я чл енам и произ в од ного, причем пос л ед ний м ожет переопред ел ит ь некоторы е из них, а т акже д обав ит ь нов ы е пол я, м етод ы и с в ойс т в а. Под переопред ел ением з д ес ь поним ает с я объяв л ение в кл ас с епотом ке чл ена с т ем же им енем , что и некоторы й чл ен кл ас с а-пред ка. Н икаких ограничений на переопред ел яем ы е чл ены не накл ад ы в ает с я, хотя в с л учае м етод ов нов ая и с т арая в ерс ия обы чноим еют од инаков ы е з агол ов ки. Объяв л ение произ в од ногокл ас с а в ы гл яд ит с л ед ующим образ ом : ИмяПотомка = class(ИмяПредка) СписокИзмененныхЧленов end;
гд е И м я П о т о м ка — л юбой д опус т им ы й ид ент ификатор, И м я П р едка — ид ент ификатор некоторогоопред ел енногоранее и д ос тупного в д анном м ес те кл ас с а, С пи с о кИ зм ененны хЧ лено в — с пис ок объяв л ений нов ы хи переопред ел енны хчл енов кл ас с а (в оз м ожно, пус той). По-прежнем у кажд ом у чл ену м ожет пред ш ес т в ов ать д ирект ив а, указ ы в ающая егообл ас т ь в ид им ос т и. При э том обл ас т ь в ид им ос т и чл ена, переопред ел яем ого в произ в од ном кл ас с е, не м ожет бы т ь с д ел ана м ень ш е, чем в баз ов ом . Кром е того, опубл иков анны е чл ены нел ь з я переопред ел ит ь как от кры т ы е. В яз ы ке Object Pascal кажд ы й кл ас с д ол жен им еть в точнос ти од ногопред ка. Е д инс тв енны м ис кл ючением из этогоправ ил а с л ужит в с т роенны й кл ас с TObject, пред с т ав л яющий с обой в ерш ину иерархии нас л ед ов ания. Вс е кл ас с ы , в объяв л ении которы хне указ аноим я пред ка, яв л яют с япрям ы м и потом кам и TObject, т ак чтов ы ражение ИмяКласса = class ... end;
рав нос ил ь нов ы ражению ИмяКласса = class(TObject) ... end;
И м енно от э того кл ас с а и унас л ед ов аны , в час т нос т и, упом инав ш иес я в ы ш е конс т руктор Create и д ес т руктор Destroy. В качес т в е прим ера рас с м от рим кл ас с д л я работ ы с p-ичны м и д робям и, тоес т ь рационал ь ны м и чис л ам и, з нам енат ел ь которы хяв л яет с я с т епень ю некоторогофикс иров анногопрос тогочис л а p.
35
Пример 3.1. И нт ерфейс кл ас с а PAryFraction. PAryFraction = class(Rational) // p-ичное рациональное число private // закрытые члены класса base: Integer; // простое число p protected // защищенные члены класса function isPrime(value: Integer): boolean; // Является простым function isPowerOfBase(value: Integer): boolean; // Является степенью base public // открытые члены класса constructor Create; constructor CreateAs(n, m: Integer); procedure SetDen(value: Integer); procedure SetBase(value: Integer); // Установить base function GetBase: Integer; // Вернуть base end;
Очев ид но, чтокажд ая p-ичная д робь характ ериз ует с я т рем я чис л ам и: чис л ит ел ем , з нам енат ел ем и прос т ы м чис л ом p, с т епень ю которогояв л яет с я з нам енат ел ь . Поэ том у к кл ас с у PAryFraction д обав л енонов ое пол е base (ос нов ание с т епени) и от кры т ы е м етод ы GetBase и SetBase д л я чт ения-з апис и его з начений. Пос кол ь ку чис л о, с охраняем ое в пол е base, с л ед ует обяз ат ел ь но пров ерят ь на прос тот у, в раз д ел protected в кл ючена с оот в ет с т в ующая функция isPrime. Дал ее, необход им о поз аботит ь с я о том , чтобы нов ое пол е в с егд а им ел о коррект ное з начение и з нам енат ел ь пред с т ав л ял с обой его с тепень . С э той цел ь ю кл ас с PAryFraction переопред ел яет конс т рукторы Create, CreateAs и м етод SetDen с в оего пред ка. Кром е того, к перечню з ащищенны хчл енов д обав л яет с я в с пом огател ь наяфункция isPowerOfBase. Обрат им с я т еперь к реал из ации нов ы хи переопред ел енны хм етод ов , пред пол агая, чтоопред ел ения с т арогои нов огокл ас с ов наход ят с я в раз ны хм од ул ях. В э том с л учае нам оказ ы в ают с я д ос т упны в с е чл ены баз ов огокл ас с а з а ис кл ючением з акры т ы х, тоес т ь в д анном конкрет ном с л учае з а ис кл ючением пол ей num и den, и з д ес ь в оз никает небол ь ш ая пробл ем а. Очев ид но, чтонов ая в ерс ия м етод а SetDen т ак ил и иначе д ол жна из м енят ь в ел ичину з нам енат ел я т екущегообъект а. Пос кол ь ку пол е den в произ в од ном кл ас с е нед ос т упно, ед инс т в енны й с пос об с д ел ат ь э то — ис пол ь з ов ат ь с т ары й в ариант той же процед уры , унас л ед ов анны й из кл ас с а Rational. Н опрос тое упом инание с обс т в енногоим ени в реал из ации м етод а SetDen буд ет в ос принятокак обы чны й рекурс ив ны й в ы з ов , что, раз ум еет с я, нам не под ход ит. 36
Дл я того, чтобы ком пил ятор м ог отл ичат ь с т ары е и нов ы е в ерс ии чл енов кл ас с а в яз ы к в в ед еноз арез ерв иров анное с л ов оinherited. Вы ражение inherited ИмяЧлена
гов орит о том , чтообращение произ в од ит с я к чл ену т екущего объект а, унас л ед ов анном у из непос ред с т в енного пред ш ес т в енника его кл ас с а в иерархии нас л ед ов ания. Указ ат ел ь self з д ес ь уже нед опус т им . Зам ет им , чтот аким образ ом м ожнопол учит ь д ос т уп л иш ь к чл енам бл ижайш егопред ка. Е с л и, с кажем , кл ас с C переопред ел ил м етод X кл ас с а B, а кл ас с B в с в ою очеред ь переопред ел ил с оот в ет с т в ующий м етод кл ас с а A, тов ы з в ат ь в ерс ию м етод а X д л я кл ас с а A при реал из ации кл ас с а C нев оз м ожно. И т ак, рас с м от рим Пример 3.2. Реал из ация кл ас с а PAryFraction. unit UnitPAryFraction; interface uses UnitRational; // подключаем модуль, // в котором реализован класс Rational type PAryFraction = class(Rational) // здесь находится приведенный выше интерфейс класса end; implementation uses SysUtils; // модуль включает поддержку исключений function PAryFraction.isPrime(value: Integer): boolean; var i:Integer; begin if value0) and self.isPowerOfBase(value) then inherited SetDen(value) else raise Exception.Create('Illegal value of denominator'); { Если передаваемое значение положительно и является степенью base, то можно изменить знаменатель, вызвав старую версию метода SetDen. Иначе возбуждается исключение с сообщением "Недопустимое значение знаменателя". } end; constructor PAryFraction.Create; begin inherited Create; // старый конструктор инициализирует поля num и den self.base:=2; end;
38
constructor PAryFraction.CreateAs(n, m: Integer); var i: Integer; begin if m