Как работают виртуальные функции в c # и java?

6 ответов

Лучший ответ

Можете ли вы писать виртуальные функции на Java?

Да. Фактически, все методы экземпляра в Java по умолчанию являются виртуальными. Только определенные методы не являются виртуальными:

  • Методы класса (поскольку обычно каждый экземпляр содержит информацию, такую ​​как указатель на vtable, о своих конкретных методах, но здесь нет доступных экземпляров).
  • Методы частного экземпляра (поскольку никакой другой класс не может получить доступ к методу, вызывающий экземпляр всегда имеет тип самого определяющего класса и, следовательно, однозначно известен во время компиляции).

Вот некоторые примеры:

«Обычные» виртуальные функции

Следующий пример взят из старой версии упомянутой страницы википедии. в другом ответе.

Выход:

I eat like a generic Animal.
I eat like a fish!
I eat like a goldfish!
I eat like a generic Animal.

Пример виртуальных функций с интерфейсами

Все методы интерфейса Java являются виртуальными. Они должны быть виртуальными, потому что они полагаются на реализующие классы для предоставления реализаций методов. Код для выполнения будет выбран только во время выполнения.

Например:

Пример виртуальных функций с абстрактными классами.

Подобно интерфейсам Абстрактные классы должны содержат виртуальные методы, потому что они полагаются на реализацию расширяющихся классов. Например:

101

20 revs, 4 users 64%
28 Окт 2019 в 06:48

Все функции в Java по умолчанию виртуальные.

Вы должны изо всех сил писать не виртуальные функции, добавляя ключевое слово final.

Это противоположность C ++ / C # по умолчанию. По умолчанию функции класса не являются виртуальными; вы делаете их такими, добавляя модификатор «виртуальный».

56

duffymo
28 Дек 2010 в 16:18

Все непубличные методы экземпляра по умолчанию в Java являются виртуальными.

В C ++ частные методы могут быть виртуальными. Это может быть использовано для идиомы невиртуального интерфейса (NVI). В Java вам нужно сделать защищенные перезаписываемые методы NVI.

Из Спецификации языка Java, v3:

9

Andy Thomas
10 Апр 2014 в 19:32

Да, вы можете писать виртуальные «функции» на Java.

4

RepDetec
28 Дек 2010 в 16:42

В Java все общедоступные (не частные) переменные и функции по умолчанию являются виртуальными . Более того, переменные и функции, в которых используется ключевое слово final , не виртуальные .

1

Parvej Ahmed
25 Сен 2016 в 00:53

Причины появления default-методов

Наверно уже понятно, что default-методы упрощают рефакторинг — а именно, добавление новых методов.

До Java 8 все методы в интерфейсах были абстрактными. К чему это вело?

К тому, что при добавлении нового метода в интерфейс приходилось править все классы, реализующие интерфейс — реализовывать метод в этих классах. Это было неудобно. А в Java 8 (в классы ядра) захотели ввести новые методы в старые интерфейсы. Так что ввели ключевое слово default и эти методы сделали default. Например, в интерфейсе java.lang.Iterable появились новые default-методы forEach() и spliterator():

public interface Iterable<T> {

    Iterator<T> iterator();

    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }

     default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

Поскольку огромное число классов реализуют Iterable , без default-методов дополнить этот интерфейс было бы практически невозможно.

Создаём каркас аннотации

Аннотации похожи на интерфейсы. Если вы пока не очень ориентируетесь в интерфейсах, освежите свои знания о них в этой статье, перед тем как мы продолжим.

Они не просто похожи на интерфейсы: под капотом JVM (виртуальная машина Java) преобразует элементы аннотации в методы интерфейса, а саму аннотацию — в имплементацию (реализацию) этого интерфейса.

Вот как выглядит объявление простейшей аннотации для отметки особо интересных каналов:

Здесь, кроме заголовка, нет ничего полезного. Такие аннотации ещё называют маркерными — они действительно просто маркируют, обозначают какой-то признак.

Как использовать:

Или так:

При использовании маркерных аннотаций можно опускать круглые скобки после названия.

В аннотациях могут быть:

  • обязательные элементы,
  • необязательные элементы,
  • константы.

Параметры класса

Мы можем создавать поля класса, каждое из которых имеет свой тип.

Поле класса — это переменная, которая описывает какое-либо из свойств данного класса.

Для наших домашних питомцев и полями класса будут вес, кличка и принадлежность к определённому типу (коровы, гуси, собаки и так далее). Очевидно, что здесь вес — это числовая переменная, а кличка и тип — строки символов. Тогда мы можем написать:

Переменные weight, name и type — поля нашего класса Pet, то есть свойства, которые описывают объект этого класса. Таких полей может быть сколько угодно, каждое имеет свой тип, как обычная переменная.

Мы уже пару раз упомянули словосочетание «объект класса». Так говорят, потому что любой объект является экземпляром какого-либо класса. Здесь действует простая аналогия: класс — это как бы чертёж, который описывает объект, его устройство, а объект — реализация чертежа, его материальное воплощение.

Давайте запрограммируем первый объект класса Pet. Пусть это будет кот (type) с кличкой (name) Барсик и весом (weight) 10 (измерение в килограммах).

Сперва необходимо создать переменную типа Pet:

Наш объект pet выглядит как обычная переменная, но в качестве типа указан класс Pet, и в данный момент в нём ничего нет. Инициализируем объект — воспользуемся такой синтаксической конструкцией:

Мы ставим знак равно, пишем ключевое слово new, имя нашего класса и круглые скобки. Принято говорить, что здесь мы вызываем конструктор класса Pet. Пока просто запомним это — о конструкторах и о том, как их использовать, будет рассказано в отдельной статье.

Теперь у нас появилась переменная pet типа Pet, в которой содержится объект класса Pet. Ранее в этом классе мы объявили поля, к которым можно обратиться и занести в них значения.

Чтобы получить доступ к какому-либо полю нашего класса Pet, нужно специальным образом обратиться к переменной pet — поставить точку и вызвать необходимое поле. Например, вот так:

Теперь во всех трёх полях есть по значению, а мы можем получить их из программы, если потребуется, — например, распечатать в консоль:

Изменить значение в любом из полей класса также несложно. Пусть наш кот Барсик слегка потолстеет — добавим к его весу 1 кг:

Как видим, мы просто изменили вес в поле weight, а при выводе получили уже другое значение.

Можете ли вы писать виртуальные функции на Java?

Да. Фактически, все методы экземпляра в Java по умолчанию являются виртуальными. Только определенные методы не являются виртуальными:

  • Методы класса (поскольку обычно каждый экземпляр содержит информацию, такую ​​как указатель на vtable, о своих конкретных методах, но здесь нет доступных экземпляров).
  • Методы частного экземпляра (поскольку никакой другой класс не может получить доступ к методу, вызывающий экземпляр всегда имеет тип самого определяющего класса и поэтому однозначно известен во время компиляции).

Вот некоторые примеры:

«Нормальные» виртуальные функции

Следующий пример взят из старой версии страницы Википедии, упомянутой в другом ответе.

Выход:

 Я ем как обычное животное. Я ем как рыбу! Я ем как золотая рыбка! Я ем как обычное животное. 

Пример с виртуальными функциями с интерфейсами

Все методы интерфейса Java являются виртуальными. Oни должен быть виртуальными, потому что они полагаются на реализующие классы для предоставления реализации методов. Код для выполнения будет выбран только во время выполнения.

Например:

Пример с виртуальными функциями с абстрактными классами.

Подобно интерфейсам Абстрактные классы должен содержат виртуальные методы, потому что они полагаются на реализацию расширяющихся классов. Например:

  • 1 Это должен быть наиболее полный ответ. Он предоставляет 2 способа реализовать виртуальную функцию, поскольку в java нет ключевого слова. Спасибо.
  • Намного лучший ответ, чем цитата из Википедии. Я пришел из C ++ и был ленив с изучением Java, поэтому я искал абстрактное.
  • @ Дэвид Как этот ответ лучше? Цитирование в Википедии является полным, кратким и правильным. В этом ответе, напротив, не упоминается слон в комнате: по умолчанию все функции в Java (за исключениями, перечисленными в статье в Википедии) являются виртуальными. Для виртуальных функций не нужны ни абстрактные классы, ни интерфейсы, так что это только добавляет вводящий в заблуждение шум. А потом это «требует отличных коммуникативных навыков и глубокого владения основными принципами» … блин. Это самоубийственное заявление: никто, у кого есть это, не будет тратить на это ценное дисковое пространство.
  • Сообщение в Википедии является неполноценным и менее конкретным для этого ответа, потому что оно касается концепции виртуальных функций на любом языке, а не только java. Пример, приведенный на странице википедии, написан на C, в лучшем случае неполный и более вводящий в заблуждение. Подробная информация о том, что все функции являются виртуальными, и что вам не нужны абстрактные классы или интерфейсы, чтобы виртуальные функции были шумом. Я никогда не говорил, что они необходимы, вы неправильно это поняли. Я не понимаю вашего последнего пункта. Вы хотите, чтобы я удалил этот вопрос, потому что он вам не нравится?
  • 1 Здесь опоздал на несколько лет, но фантастический ответ

Все функции в Java по умолчанию виртуальные.

Вы должны изо всех сил писать не виртуальные функции, добавляя ключевое слово final.

Это противоположность C ++ / C # по умолчанию. По умолчанию функции класса не являются виртуальными; вы делаете их такими, добавляя модификатор «виртуальный».

4 частные функции, как указано в ответе Клауса, также не являются виртуальными.

Все не частный Методы экземпляра в Java по умолчанию являются виртуальными.

В C ++ частные методы могут быть виртуальными. Это может быть использовано для идиомы невиртуального интерфейса (NVI). В Java вам нужно сделать защищенные перезаписываемые методы NVI.

Из Спецификации языка Java, v3:

Да, вы можете писать виртуальные «функции» на Java.

В Java все общедоступные (не частные) переменные и функции Виртуальный по умолчанию. Кроме того, переменные и функции с использованием ключевого слова окончательный не виртуальный.

что вы подразумеваете под «виртуальными переменными»?

Как наследуются default-методы

Возникает вопрос, какой метод унаследует класс, реализующий два интерфейса, если оба из них содержат default-методы с одинаковыми именами.

Например, есть второй интерфейс Man, который тоже содержит свой default метод sleep():

public interface Man {
    default String sleep() {
        return ("man sleeps");
    }
}

И есть класс Kentavr, реализующий как интерфейс Man, так и Animal. Какой же метод sleep() унаследует Kentavr?

Чтобы не было неопределенности (и чтобы скомпилировался код),  мы обязаны переопределить в Kentavr метод sleep(), причем можно просто вызвать в нем метод sleep() любого из интерфейсов — Man либо Animal, указав через точку и super, чей именно метод нужен:

public class Kentavr implements Man, Animal{

    @Override
    public String move() {
	return "kentavr moves";
    }

    @Override
    public String sleep() {
	return Man.super.sleep();
    }
}

Убедимся, что кентавр спит по-человечески:

@Test
public void whenKentavrSleep_thenSpecifyWhose() {
    assertEquals("man sleeps", kentavr.sleep());
}

Определяем область действия

К чему применима аннотация

До этого шага мы использовали аннотации только для классов, но они применимы к интерфейсам, методам, параметрам класса, локальным переменным и не только. За область применимости аннотации отвечает другая аннотация — @Target. Полный список доступных значений для её единственного элемента value есть в официальной документации.

Если не задавать @Target, аннотацию можно использовать для любых программных элементов.

Мы же для примера напишем аннотацию, которая будет применима к методам и конструкторам классов. Предположим, она будет показывать, что после выполнения таких конструкторов и таких методов нужно будет отправить кому-то тревожное сообщение. Реализацию обработчика оставим за кадром, а аннотация будет выглядеть так:

Как использовать:

Если теперь попробуем написать @Alarm перед названием самого класса SecureChannel, получим ошибку компиляции, потому что в @Target не включено значение для типа элемента «класс».

Когда аннотация доступна

Если мы и правда хотим прямо во время выполнения программы искать какие-то помеченные аннотацией @Alarm методы, одним только указанием @Target не обойтись.

Есть ещё одна аннотация для описания аннотаций — это @Retention. Она определяет доступность в течение жизненного цикла программы. У её единственного элемента value всего три доступных значения:

Значение Описание
RetentionPolicy.SOURCE Аннотация останется только в файлах исходников, в .class-файлы сведения о ней не попадут
RetentionPolicy.CLASS — значение по умолчанию Аннотация будет сохранена в .class-файлах, но не будет доступна во время выполнения программы
RetentionPolicy.RUNTIME Аннотация будет сохранена в .class-файлах, доступна во время выполнения программы

Воспользуемся новыми знаниями и допишем нашу тревожную аннотацию:

Теперь она будет доступна в рантайме, что и требовалось.

Делаем аннотацию повторяющейся

Вернёмся к аннотации для описания хобби и зададимся вопросом: что, если в канале попадается информация о нескольких увлечениях? Например, в нём публикуются обзоры новых фильмов и афиши концертов — вроде и про кино, и про музыку.

Попробуем пометить класс такого универсального канала сразу двумя @Hobby с разными значениями элементов:

Иии… получим ошибку компиляции! Вот такую:

Что ж, сделаем её repeatable, то есть повторяющейся. Для этого опять понадобится аннотация — @Repeatable. Пометим ею @Hobby:

Но снова натыкаемся на возражения компилятора: оказывается, у @Repeatable должен быть указан обязательный элемент, а тип этого элемента — ещё одна аннотация

Глубоко выдохнем и создадим её. В этой очередной аннотации нужно указать, какую другую аннотацию — в нашем случае @Hobby — мы собираемся повторять:

И последний шажок — укажем класс этой новой аннотации в качестве значения для @Repeatable:

Можете ли вы писать виртуальные функции на Java?

Да. Фактически, все методы экземпляра в Java по умолчанию являются виртуальными. Только определенные методы не являются виртуальными:

  • Методы класса (потому что обычно каждый экземпляр содержит информацию, такую ​​как указатель на vtable о своих конкретных методах, но здесь нет доступных экземпляров).
  • Методы частного экземпляра (поскольку никакой другой класс не может получить доступ к методу, вызывающий экземпляр всегда имеет тип самого определяющего класса и поэтому однозначно известен во время компиляции).

Вот некоторые примеры:

«Нормальные» виртуальные функции

Следующий пример взят из старой версии страницы Википедии, упомянутой в другом ответе.

Выход:

 Я ем как обычное животное. Я ем как рыбу! Я ем как золотая рыбка! Я ем как обычное животное. 

Пример с виртуальными функциями с интерфейсами

Все методы интерфейса Java виртуальны. Oни должен быть виртуальными, потому что они полагаются на реализующие классы для предоставления реализации методов. Код для выполнения будет выбран только во время выполнения.

Например:

Пример с виртуальными функциями с абстрактными классами.

Подобно интерфейсам Абстрактные классы должен содержат виртуальные методы, потому что они полагаются на реализацию расширяющихся классов. Например:

  • 1 Это должен быть наиболее полный ответ. Он предоставляет 2 способа реализовать виртуальную функцию, поскольку в java нет ключевого слова. Спасибо.
  • Намного лучший ответ, чем цитата из Википедии. Я пришел из C ++ и был ленив с изучением Java, поэтому я искал абстрактное.
  • @ Дэвид Как этот ответ лучше? Цитирование в Википедии является полным, кратким и правильным. В этом ответе, напротив, не упоминается слон в комнате: по умолчанию все функции в Java (за исключениями, перечисленными в статье в Википедии) являются виртуальными. Для виртуальных функций не нужны ни абстрактные классы, ни интерфейсы, так что это только добавляет вводящий в заблуждение шум. А потом это «требует отличных коммуникативных навыков и глубокого владения основными принципами» … блин. Это самоубийственное заявление: никто, у кого есть это, не будет тратить на это ценное дисковое пространство.
  • Сообщение в Википедии является неполноценным и менее конкретным для этого ответа, потому что оно касается концепции виртуальных функций на любом языке, а не только java. Пример, приведенный на странице википедии, написан на C, и в лучшем случае он неполный и вводит в заблуждение. Подробная информация о том, что все функции являются виртуальными, и что вам не нужны абстрактные классы или интерфейсы, чтобы виртуальные функции были шумом. Я никогда не говорил, что они необходимы, вы неправильно это поняли. Я не понимаю вашего последнего пункта. Вы хотите, чтобы я удалил этот вопрос, потому что он вам не нравится?
  • 1 Здесь опоздал на несколько лет, но фантастический ответ

Все функции в Java по умолчанию виртуальные.

Вы должны изо всех сил писать не виртуальные функции, добавляя ключевое слово final.

Это противоположность C ++ / C # по умолчанию. По умолчанию функции класса не являются виртуальными; вы делаете их такими, добавляя модификатор «виртуальный».

4 частные функции, как указано в ответе Клауса, также не являются виртуальными.

Все не частный Методы экземпляра в Java по умолчанию являются виртуальными.

В C ++ частные методы могут быть виртуальными. Это может быть использовано для идиомы невиртуального интерфейса (NVI). В Java вам нужно сделать защищенные перезаписываемые методы NVI.

Из Спецификации языка Java, v3:

Да, вы можете писать виртуальные «функции» на Java.

В Java все общедоступные (не частные) переменные и функции Виртуальный по умолчанию. Кроме того, переменные и функции с использованием ключевого слова окончательный не виртуальный.

что вы подразумеваете под «виртуальными переменными»?

Редактор-автор

Можете ли вы писать виртуальные функции на Java?

Да.Фактически, все методы экземпляра в Java по умолчанию являются виртуальными. Только определенные методы не являются виртуальными:

  • Методы класса (поскольку обычно каждый экземпляр содержит информацию, такую ​​как указатель на vtable, о своих конкретных методах, но здесь нет доступных экземпляров).
  • Методы частного экземпляра (поскольку никакой другой класс не может получить доступ к методу, вызывающий экземпляр всегда имеет тип самого определяющего класса и поэтому однозначно известен во время компиляции).

Вот некоторые примеры:

«Нормальные» виртуальные функции

Следующий пример взят из старой версии страницы Википедии, упомянутой в другом ответе.

Выход:

 Я ем как обычное животное. Я ем как рыбу! Я ем как золотая рыбка! Я ем как обычное животное. 

Пример с виртуальными функциями с интерфейсами

Все методы интерфейса Java виртуальны. Oни должен быть виртуальными, потому что они полагаются на реализующие классы для предоставления реализации методов. Код для выполнения будет выбран только во время выполнения.

Например:

Пример с виртуальными функциями с абстрактными классами.

Подобно интерфейсам Абстрактные классы должен содержат виртуальные методы, потому что они полагаются на реализацию расширяющихся классов. Например:

  • 1 Это должен быть наиболее полный ответ. Он предоставляет 2 способа реализовать виртуальную функцию, поскольку в java нет ключевого слова. Спасибо.
  • Намного лучший ответ, чем цитата из Википедии. Я пришел из C ++ и был ленив с изучением Java, поэтому я искал абстрактное.
  • @ Дэвид Как этот ответ лучше? Цитирование в Википедии является полным, кратким и правильным. В этом ответе, напротив, не упоминается слон в комнате: по умолчанию все функции в Java (за исключениями, перечисленными в статье в Википедии) являются виртуальными. Для виртуальных функций не нужны ни абстрактные классы, ни интерфейсы, так что это только добавляет вводящий в заблуждение шум. А потом это «требует отличных коммуникативных навыков и глубокого владения основными принципами» … блин. Это самоубийственное заявление: никто, у кого было это, не стал бы тратить на это ценное дисковое пространство.
  • Сообщение в Википедии является неполноценным и менее конкретным для этого ответа, потому что оно касается концепции виртуальных функций на любом языке, а не только java. Пример, приведенный на странице википедии, написан на C, и в лучшем случае он неполный и вводит в заблуждение. Подробная информация о том, что все функции являются виртуальными, и что вам не нужны абстрактные классы или интерфейсы, чтобы виртуальные функции были шумом. Я никогда не говорил, что они необходимы, вы неправильно это поняли. Я не понимаю вашего последнего пункта. Вы хотите, чтобы я удалил этот вопрос, потому что он вам не нравится?
  • 1 Здесь опоздал на несколько лет, но фантастический ответ

Все функции в Java по умолчанию виртуальные.

Вы должны изо всех сил писать не виртуальные функции, добавляя ключевое слово final.

Это противоположность C ++ / C # по умолчанию. По умолчанию функции класса не являются виртуальными; вы делаете их такими, добавляя модификатор «виртуальный».

4 частные функции, как указано в ответе Клауса, также не являются виртуальными.

Все не частный Методы экземпляра в Java по умолчанию являются виртуальными.

В C ++ частные методы могут быть виртуальными. Это может быть использовано для идиомы невиртуального интерфейса (NVI). В Java вам нужно сделать защищенные перезаписываемые методы NVI.

Из Спецификации языка Java, v3:

Да, вы можете писать виртуальные «функции» на Java.

В Java все общедоступные (не частные) переменные и функции Виртуальный по умолчанию. Кроме того, переменные и функции с использованием ключевого слова окончательный не виртуальный.

что вы подразумеваете под «виртуальными переменными»?

Редактор-автор

Пример использования

Допустим, у нас есть интерфейс Animal:

public interface Animal {
	String move();
}

Есть классы Cat и Fish, реализующие интерфейс Animal:

public class Cat implements Animal {
	@Override
	public String move() {
		return "run";
	}
}
public class Fish implements Animal {
	@Override
	public String move() {
		return "swim";
	}
}

Мы хотим добавить в интерфейс Animal метод sleep(), при этом не реализовывать его в каждом классе, а реализовать непосредственно в интерфейсе. Классы же будут наследовать этот метод по умолчанию. Для этого наш метод надо обозначить как default:

public interface Animal {

	String move();

	default String sleep() {
		return ("sleep");
	}
}

Теперь этот метод унаследуют все животные:

@Test
public void whenCatSleep_thenOk() {
    assertEquals("sleep", cat.sleep());
}

Впрочем, его можно и переопределить в каком-либо из классов, например в Fish:

public class Fish implements Animal {

    @Override
    public String move() {
	return "swim";
    }

    @Override
    public String sleep() {
	return "fish sleeps";
    }
}

Убедимся, что рыба спит по-своему:

@Test
public void whenFishSleep_thenOnItsOwn() {
    assertEquals("fish sleeps", fish.sleep());
}

Методы класса

В начале статьи я упомянул, что наши домашние животные могут перемещаться и есть. В отличие от параметров вроде веса и клички, это уже не свойства объекта, а его функции. В классе эти функции обозначают как методы.

Метод класса — это блок кода, состоящий из ряда инструкций, который можно вызывать по его имени. Он обязательно содержит возвращаемый тип, название, аргументы и тело метода.

Синтаксис метода в Java:

Строка возвращаемыйТип показывает, какого типа данные вернёт метод. Например, если в качестве возвращаемого типа мы поставим тип String, то метод должен будет вернуть строку, а если int — целое число.

Чтобы вернуть значение из метода, используется специальное слово return. Если мы хотим, чтобы метод ничего не возвращал, то вместо возвращаемого типа нужно использовать специальное слово void.

Аргументы — то, что нужно передать в метод при его вызове. Мы можем указать сколько угодно параметров через запятую либо не указывать ни одного.

Для примера напишем простейший метод с именем sum (пока что не в нашем классе Pet), который складывает два переданных числа и возвращает их результат:

Возвращаемый тип метода int, он указан перед именем sum. Далее идут два аргумента a и b, у обоих также указан тип int

Важно помнить, что возвращаемый тип и тип переменных не обязательно должны совпадать

Аргументы метода работают как обычные переменные — за пределами метода к ним никак нельзя получить доступ. Внутри метода мы складываем значения из переменных a и b, записываем полученное значение в переменную c. После этого мы возвращаем значение переменной c — только оно доступно вне метода.

Вот пример:

Мы передали в метод sum два значения 1 и 2, а на выходе получили результат их сложения 3. Также можно создать метод, который принимает значение типа String, а возвращает длину этой строки:

В этом случае у нас возвращаемый типа int, а параметр str — типа String.

Попробуем использовать этот метод:

Также мы можем создать метод, который ничего не возвращает, а просто печатает переданное слово в консоль:

Либо метод, который ничего не принимает на вход, а просто печатает «Привет!»:

В методах, которые ничего не возвращают, слово return можно опустить.

Обратите внимание, что return полностью прекращает выполнение метода:

Теперь попробуем вызвать этот метод, передав в него число 3:

В этом случае мы ничего не увидим в консоли, так как 3 меньше 5, а значит, отработает блок if и произойдёт выход из метода с помощью слова return.

Но если передадим 6, увидим нашу надпись «Привет!»:

Можете ли вы писать виртуальные функции на Java?

Да. Фактически, все методы экземпляра в Java по умолчанию являются виртуальными. Только определенные методы не являются виртуальными:

  • Методы класса (поскольку обычно каждый экземпляр содержит информацию, такую ​​как указатель на vtable, о своих конкретных методах, но здесь нет доступных экземпляров).
  • Методы частного экземпляра (поскольку никакой другой класс не может получить доступ к методу, вызывающий экземпляр всегда имеет тип самого определяющего класса и поэтому однозначно известен во время компиляции).

Вот некоторые примеры:

«Нормальные» виртуальные функции

Следующий пример взят из старой версии страницы Википедии, упомянутой в другом ответе.

Вывод:

 Я ем как обычное животное. Я ем как рыбу! Я ем как золотая рыбка! Я ем как обычное животное. 

Пример с виртуальными функциями с интерфейсами

Все методы интерфейса Java являются виртуальными. Oни должен быть виртуальными, потому что они полагаются на реализующие классы для предоставления реализации методов. Код для выполнения будет выбран только во время выполнения.

Например:

Пример с виртуальными функциями с абстрактными классами.

Подобно интерфейсам Абстрактные классы должен содержат виртуальные методы, потому что они полагаются на реализацию расширяющихся классов. Например:

  • 1 Это должен быть наиболее полный ответ. Он предоставляет 2 способа реализовать виртуальную функцию, поскольку в java нет ключевого слова. Спасибо.
  • Намного лучший ответ, чем цитата из Википедии. Я пришел из C ++ и был ленив с изучением Java, поэтому я искал абстрактное.
  • @ Дэвид Как этот ответ лучше? Цитирование в Википедии является полным, кратким и правильным. В этом ответе, напротив, не упоминается слон в комнате: по умолчанию все функции в Java (за исключениями, перечисленными в статье в Википедии) являются виртуальными. Для виртуальных функций не нужны ни абстрактные классы, ни интерфейсы, так что это только добавляет вводящий в заблуждение шум. А потом это «требует отличных коммуникативных навыков и глубокого владения основными принципами» … блин. Это самоубийственное заявление: никто, у кого есть это, не будет тратить на это ценное дисковое пространство.
  • Сообщение в Википедии является неполноценным и менее конкретным для этого ответа, потому что оно касается концепции виртуальных функций на любом языке, а не только java. Пример, приведенный на странице википедии, написан на C, и в лучшем случае он неполный и вводит в заблуждение. Подробная информация о том, что все функции являются виртуальными, и что вам не нужны абстрактные классы или интерфейсы, чтобы виртуальные функции были шумом. Я никогда не говорил, что они необходимы, вы неправильно это поняли. Я не понимаю вашего последнего пункта. Вы хотите, чтобы я удалил этот вопрос, потому что он вам не нравится?
  • 1 Здесь опоздал на несколько лет, но фантастический ответ

Все функции в Java по умолчанию виртуальные.

Вы должны изо всех сил писать не виртуальные функции, добавляя ключевое слово final.

Это противоположность C ++ / C # по умолчанию. По умолчанию функции класса не являются виртуальными; вы делаете их такими, добавляя модификатор «виртуальный».

4 частные функции, как указано в ответе Клауса, также не являются виртуальными.

Все не частный Методы экземпляра в Java по умолчанию являются виртуальными.

В C ++ частные методы могут быть виртуальными. Это может быть использовано для идиомы невиртуального интерфейса (NVI). В Java вам нужно сделать защищенные перезаписываемые методы NVI.

Из Спецификации языка Java, v3:

Да, вы можете писать виртуальные «функции» на Java.

В Java все общедоступные (не частные) переменные и функции Виртуальный по умолчанию. Кроме того, переменные и функции с использованием ключевого слова окончательный не виртуальный.

что вы подразумеваете под «виртуальными переменными»?

Статические переменные Java

  • Статическая переменная может использоваться для обозначения общего свойства всех объектов (которое не является уникальным для каждого объекта), например название компании, колледжа и т. д.
  • Статическая переменная задействует память только один раз во время загрузки класса.

Статические переменные в Java — преимущества

Java static переменная не загружает память.

Пример, в котором не используется статическая переменная

class Student{  
     int rollno;  
     String name;  
     String college="ITS";  
}

Предположим, что в колледже 500 студентов. Класс Student будут задействовать память каждый раз при создании объекта. У всех студентов есть уникальное rollno и name. А college — это общее свойство для всех объектов. Если сделать его статическим, то поле будет задействовать память только один раз.

Статическое свойство Java является общим для всех объектов.

Пример статической переменной

//Программа со статической переменной

class Student8{  
   int rollno;  
   String name;  
   static String college ="ITS";

   Student8(int r,String n){  
   rollno = r;  
   name = n;  
   }  
 void display (){System.out.println(rollno+" "+name+" "+college);}

 public static void main(String args[]){  
 Student8 s1 = new Student8(111,"Karan");  
 Student8 s2 = new Student8(222,"Aryan");

 s1.display();  
 s2.display();  
 }  
}

Проверить сейчас

Вывод:111 Karan ITS
	  222 Aryan ITS

Программа подсчета без статической переменной

В этом примере мы создаем Java static переменную count, которая увеличивается в конструкторе. Поскольку переменная экземпляра задействует память только во время создания объекта, то каждый объект ее копию. Поэтому при увеличении переменной он не будет влиять на другие объекты. Каждый объект получит значение 1 в переменной count.

class Counter{  
int count=0;//использует память при создании экземпляра

Counter(){  
count++;  
System.out.println(count);  
}

public static void main(String args[]){

Counter c1=new Counter();  
Counter c2=new Counter();  
Counter c3=new Counter();

 }  
}

Проверить сейчас

Вывод: 1
	  1
	  1

Программа подсчета со статической переменной

Java static переменная задействует память только один раз. Если какой-либо объект изменяет значение статической переменной, она сохраняет свое значение.

class Counter2{  
static int count=0;//использует память только один раз и сохраняет значение переменной

Counter2(){  
count++;  
System.out.println(count);  
}

public static void main(String args[]){

Counter2 c1=new Counter2();  
Counter2 c2=new Counter2();  
Counter2 c3=new Counter2();

 }  
}

Проверить сейчас

Вывод: 1
	  2
	  3
Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Все про сервера
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: