Из Википедии, свободной энциклопедии
Перейти к навигации Перейти к поиску
Иллюстрация

Переопределение метода в объектно-ориентированном программировании - это языковая функция, которая позволяет подклассу или дочернему классу предоставлять конкретную реализацию метода, который уже предоставлен одним из его суперклассов или родительских классов. Реализация в подклассе переопределяет (заменяет) реализацию в суперклассе, предоставляя метод с тем же именем, такими же параметрами или сигнатурой и тем же возвращаемым типом, что и метод в родительском классе. [1] Версия выполняемого метода будет определяться объектомкоторый используется для его вызова. Если для вызова метода используется объект родительского класса, то будет выполнена версия в родительском классе, но если для вызова метода используется объект подкласса, то будет выполнена версия в дочернем классе. [2] Некоторые языки позволяют программисту предотвратить переопределение метода.

У него такая же подпись с тем же типом аргумента, который был переопределен в дочернем классе.

Примеры для конкретных языков [ править ]

Ада [ править ]

Ада по умолчанию обеспечивает переопределение метода. Чтобы способствовать раннему обнаружению ошибок (например, орфографической ошибки), можно указать, когда метод, как ожидается, будет фактически заменять или нет. Это будет проверено компилятором.

 типа  Т  является  новым  Controlled  с  ......;  процедура  Op ( Obj : in  out  T ;  Data : in  Integer ); тип  NT  -  новый  T  с  нулевой записью ;  overriding  - переопределение индикаторной  процедуры  Op ( Obj : in  out  NT ;  Data : in  Integer );  overriding  - переопределение индикаторной  процедуры  Op ( Obj : in  out  NT ;  Data : in  String );  - ^ компилятор выдает ошибку: подпрограмма "Op" не отменяет

C # [ править ]

C # поддерживает переопределение методов, но только в случае явного запроса с использованием модификаторов overrideи virtualили abstract.

абстрактный  класс  Animal {  общедоступная  строка  Имя  {  получить ;  набор ;  }  // Методы  public  void  Drink ();  общедоступная  виртуальная  пустота  Eat ();  public  void  Go (); }class  Cat  :  Animal {  общедоступная  новая  строка  Имя  {  получить ;  набор ;  }  // Методы  public  void  Drink ();  // Предупреждение: скрывает унаследованный drink (). Использовать новое  общедоступное  переопределение  void  Eat ();  // Переопределяет унаследованный eat ().  общедоступный  новый  void  Go ();  // Скрывает унаследованный go (). }

При замене одного метода другим сигнатуры двух методов должны быть идентичными (и с одинаковой видимостью). В C # все методы класса , индексаторы , свойства и события могут быть переопределены.

Невиртуальные или статические методы нельзя переопределить. Переопределенный базовый метод должен быть виртуальным , абстрактным или переопределяемым .

В дополнение к модификаторам, которые используются для переопределения метода, C # позволяет скрыть унаследованное свойство или метод. Это делается с использованием той же сигнатуры свойства или метода, но с добавлением модификатора newперед ним. [3]

В приведенном выше примере скрытие вызывает следующее:

Кот  кот  =  новый  Кот ();кот . Имя  =  ;  // обращается к Cat.Name cat . Ешьте ();  // вызывает Cat.Eat () cat . Перейти ();  // вызывает Cat.Go () (( Animal ) cat ). Имя  =  ;  // обращается к Animal.Name! (( Животное ) кошка ). Ешьте ();  // вызывает Cat.Eat ()! (( Животное ) кошка ). Перейти ();  // вызывает Animal.Go ()!

C ++ [ править ]

В C ++ нет ключевого слова, superкоторое подкласс может использовать в Java для вызова версии суперкласса метода, который он хочет переопределить. Вместо этого используется имя родительского или базового класса, за которым следует оператор разрешения области видимости . Например, следующий код представляет два класса : базовый класс Rectangleи производный класс Box. Boxпереопределяет метод Rectangleкласса Print, чтобы также напечатать его высоту. [4]

#include  <iostream>// ------------------------------------------------ --------------------------- class  Rectangle  {  public :  Rectangle ( double  l ,  double  w )  :  length_ ( l ),  width_ ( w )  {}  виртуальная  пустота  Print ()  const ; частный :  двойная  длина_ ;  двойная  ширина_ ; };// ------------------------------------------------ --------------------------- void  Rectangle :: Print ()  const  {  // Метод печати базового класса.  std :: cout  <<  "Length ="  <<  length_  <<  "; Width ="  <<  width_ ; }// ------------------------------------------------ --------------------------- class  Box  :  public  Rectangle  {  public :  Box ( double  l ,  double  w ,  double  h )  :  Rectangle ( l ,  w ),  height_ ( h )  {}  void  Print ()  const  override ; частный :  двойная  высота_ ; };// ------------------------------------------------ --------------------------- // Печать метода производного класса. void  Box :: Print ()  const  {  // Вызов родительского метода Print.  Прямоугольник :: Печать ();  std :: cout  <<  "; Height ="  <<  height_ ; }

Метод Printв классе Box, вызывая родительскую версию метода Print, также может выводить частные переменные length и widthбазовый класс. В противном случае эти переменные недоступны для Box.

Следующие операторы будут создавать экземпляры объектов типа Rectangleи Boxи вызывать их соответствующие Printметоды:

int  main ( int  argc ,  char **  argv )  {  Прямоугольник  прямоугольник ( 5.0 ,  3.0 ); // Вывод: Length = 5.0; Ширина = 3,0  прямоугольника . Печать (); Коробка  коробка ( 6.0 ,  5.0 ,  4.0 ); // Указатель на наиболее переопределяемый метод в vtable в Box :: print,  // но этот вызов не иллюстрирует переопределение.  коробка . Печать (); // Этот вызов иллюстрирует переопределение.  // выводит: Length = 6.0; Ширина = 5,0; Высота = 4.0  static_cast < Прямоугольник &> ( прямоугольник ). Печать (); }

В C ++ 11 , как и в Java, метод, объявленный finalв суперклассе, не может быть переопределен; Кроме того, можно объявить метод, overrideчтобы компилятор проверял, переопределяет ли он метод в базовом классе.

Delphi [ править ]

В Delphi переопределение метода выполняется с помощью переопределения директивы , но только в том случае, если метод был отмечен динамическими или виртуальными директивами.

Унаследовали зарезервированное слово должно быть названо , когда вы хотите назвать супер-класс поведения

тип  TRectangle  =  частный класс  FLength : Double ; FWidth : двойной ; публичное свойство Длина чтения FLength write FLength ; свойство Ширина читать FWidth писать FWidth ;                  процедура  Print ;  виртуальный ;  конец ; TBox  =  class ( TRectangle )  публичная  процедура  Print ;  переопределить ;  конец ;

Эйфель [ править ]

В Eiffel , функция переопределение аналогичен методу переопределяя в C ++ и Java. Переопределение - это одна из трех форм адаптации функций, классифицируемых как переопределение . Переопределение также охватывает осуществления , в котором реализация предусмотрена функция , которая была отсроченной (реферат) в родительском классе, и undefinition , в котором особенность , которая была эффективной (бетон) в родительском становится отложено снова в классе наследника. Когда функция переопределяется, имя функции сохраняется наследником класса, но свойства функции, такие как ее подпись, контракт (с учетом ограничений для предусловий и постусловий), и / или реализация будет отличаться в наследнике. Если исходный объект в родительском классе, называемый предшественником объекта-наследника , эффективен, то будет действовать переопределенный объект в наследнике. Если предшественник отложен, функция наследника будет отложена. [5]

Намерение переопределить функцию, как messageв примере ниже, должно быть явно объявлено в inheritпредложении класса-наследника.

 сообщение функции class THOUGHT - Показать мысленное сообщение do print ( «Я чувствую, что припаркован по диагонали в параллельной вселенной.% N» ) конец конец      class  ADVICE наследовать  THOUGHT  переопределить  сообщение  end feature  message  - Предшественник  do  print  ( «Предупреждение: даты в календаре ближе, чем они появляются.% N» )  end end

В классе ADVICEфункции messageпредоставляется реализация, которая отличается от реализации ее предшественника в классе THOUGHT.

Рассмотрим класс, который использует экземпляры для THOUGHTи ADVICE:

class  APPLICATION create  make feature  make  - Запустить приложение.  делать  ( создать  { МЫСЛЬ }). сообщение ;  ( создать  { СОВЕТ }). конец сообщения  конец

При APPLICATIONсоздании экземпляра класс выдает следующий результат:

Я чувствую себя припаркованным по диагонали в параллельной вселенной.Предупреждение: даты в календаре ближе, чем кажутся.

В переопределенной функции доступ к предшественнику функции можно получить с помощью ключевого слова language Precursor. Предположим, что реализация изменена следующим образом:{ADVICE}.message

 message  - Preursor  do  print  ( «Предупреждение: даты в календаре ближе, чем они кажутся.% N» )  Конец предшественника 

Вызов функции теперь включает выполнение и дает следующий результат:{THOUGHT}.message

Предупреждение: даты в календаре ближе, чем кажутся.Я чувствую себя припаркованным по диагонали в параллельной вселенной.

Java [ править ]

В Java , когда подкласс содержит метод, который переопределяет метод суперкласса, он также может вызывать метод суперкласса с помощью ключевого слова super . [2] Пример:

class  Thought  {  public  void  message ()  {  System . из . println ( "Мне кажется, что я припаркован по диагонали в параллельной вселенной." );  } }открытый  класс  Advice  расширяет  Thought  {  @Override  // Аннотация @Override в Java 5 не является обязательной, но полезной.  public  void  message ()  {  System . из . println ( "Предупреждение: даты в календаре ближе, чем кажутся." );  } }

Класс Thoughtпредставляет суперкласс и реализует вызов метода . Вызываемый подкласс наследует все методы, которые могут быть в классе. Однако класс переопределяет метод , заменяя его функциональность из .message()AdviceThoughtAdvicemessage()Thought

 Парковка  мыслей =  новая  мысль (); парковка . сообщение ();  // Печатает «Мне кажется, что я припаркован по диагонали в параллельной вселенной». Даты  мысли =  новый  совет ();  // Полиморфизм дат . сообщение ();  // Выводит «Предупреждение: даты в календаре ближе, чем кажется».

superСсылка может быть

открытый  класс  Advice  расширяет  Thought  {  @Override  public  void  message ()  {  System . из . println ( "Предупреждение: даты в календаре ближе, чем кажутся." );  супер . сообщение ();  // Вызов родительской версии метода.  }

Есть методы, которые подкласс не может переопределить. Например, в Java метод, объявленный как final в суперклассе, не может быть переопределен. Методы, объявленные частными или статическими, нельзя переопределить, потому что они неявно являются окончательными. Также невозможно, чтобы класс, объявленный final, стал суперклассом. [6]

Котлин [ править ]

В Kotlin мы можем просто переопределить такую ​​функцию: обратите внимание, что функция должна быть открытой.

весело  main ( args :  Array < String > )  {  var  t  =  test ( 5 )  var  s  =  test2 ( 6 )  t . myFun ()  s . myFun () } тест открытого класса  ( var a : Int ) { open fun myFun () = println ( a ) }         class  test2 ( var  b  :  Int )  :  test ( b )  {  переопределить  fun  myFun ()  =  println ( "переопределенный метод" ) }

Python [ править ]

В Python , когда подкласс содержит метод, который переопределяет метод суперкласса, вы также можете вызвать метод суперкласса, вызвав [7] вместо . Пример:super(Subclass, self).methodself.method

class  Thought :  def  __init__ ( self )  ->  None :  print ( «Я новый объект типа Thought!» )  def  message ( self )  ->  None :  print ( «Мне кажется, что я припаркован по диагонали в параллельной вселенной. . " )class  Advice ( Мысль ):  def  __init__ ( self )  ->  None :  super ( Advice ,  self ) . __init__ ()  def  message ( self )  ->  None :  print ( «Предупреждение: даты в календаре ближе, чем они кажутся» )  super ( Advice ,  self ) . сообщение ()t  =  Thought () # "Я новый объект типа Thought!" т . message () # "Мне кажется, что я припаркован по диагонали в параллельной вселенной.a  =  Advice () # "Я новый объект типа Мысль!" а . message () # "Предупреждение: даты в календаре ближе, чем кажется" # "Мне кажется, что я припаркован по диагонали в параллельной вселенной.# ------------------ # Самоанализ:isinstance ( t ,  Мысль ) # Истинаisinstance ( a ,  Совет ) # Trueisinstance ( a ,  Мысль ) # Истина

Руби [ править ]

В Ruby, когда подкласс содержит метод, который переопределяет метод суперкласса, вы также можете вызвать метод суперкласса, вызвав super в этом переопределенном методе. Вы можете использовать псевдоним, если хотите, чтобы переопределенный метод был доступен вне метода переопределения, как показано ниже с помощью «super_message».

Пример:

классового  мысли  DEF  сообщение  путы  «Я чувствую, что я по диагонали припаркован в параллельной вселенной.»  конец конецclass  Advice  <  Псевдоним мысли  : super_message : message def message помещает «Предупреждение: даты в календаре ближе, чем они кажутся» super end end        

Заметки [ править ]

  1. Перейти ↑ Flanagan 2002, p. 107
  2. ^ a b Льюис и Лофтус 2006, стр.454
  3. ^ Mössenböck, Hanspeter (2002-03-25). «Расширенный C #: переопределение методов» (PDF) . http://ssw.jku.at/Teaching/Lectures/CSharp/Tutorial/ : Institut für Systemsoftware, Университет Йоханнеса Кеплера в Линце, Fachbereich Informatik. С. 6–8 . Проверено 2 августа 2011 .
  4. ^ Малик 2006, стр. 676
  5. ^ Мейер 2009, стр. 572-575
  6. ^ Дейтель & Дейтель 2001, p.474
  7. ^ в Python 3 - см. https://docs.python.org/3/library/functions.html#super Архивировано 26 октября 2018 г. на Wayback Machinesuper().method

См. Также [ править ]

  • Наследование реализации
  • Семантика наследования
  • Перегрузка метода
  • Полиморфизм в объектно-ориентированном программировании
  • Шаблон метода шаблона
  • Виртуальное наследование
  • HTTP-заголовок X-HTTP-Method-Override

Ссылки [ править ]

  • Дейтель, Х. М. и Дейтель, П.Дж. (2001). Java, как программировать (4-е изд.). Река Аппер Сэдл, штат Нью-Джерси: Prentice Hall.
  • Льюис, Дж. И Лофтус, В. (2008). Java: программные решения (6-е изд.). Бостон, Массачусетс: Пирсон Аддисон Уэсли.
  • Малик, Д.С. (2006). Программирование на C ++: проектирование программ, включая структуру данных. (3-е изд.). Вашингтон, округ Колумбия: Технология курса.
  • Фланаган, Дэвид. (2002). Java в двух словах. Получено с http://oreilly.com/catalog/9780596002831/preview#preview.
  • Мейер, Бертран (2009). Touch of Class: Учимся хорошо программировать с объектами и контрактами . Springer.

Внешние ссылки [ править ]

  • Переопределение метода Java от Хеманта Баладжи
  • Введение в концепции ООП и многое другое от Nirosh LwC
  • Методы переопределения и сокрытия с помощью Sun Microsystems