LINUX.ORG.RU
решено ФорумTalks

[жж][java]abstract private impossible

 ,


0

2

Сегодня с удивлением для себя открыл полное отсутствие возможности создать abstract private методы в яве.

+ немного новостей с reddit

Сегодня открылась конференция ICFP2010. Никаких видео презентаций пока что-то не видно - но видимо должны к коцу недели появится.

26 сентября вышел релиз кандидат Haskell ANNOUNCE: GHC 7.0.1 Release Candidate 1 Все желающие приглашаются на тестирование.


>Сегодня с удивлением для себя открыл полное отсутствие возможности создать abstract private методы в яве.

А зачем?

shuthdar ★★★
()

Сегодня с удивлением для себя открыл полное отсутствие возможности создать abstract private методы в яве.

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

Nagwal ★★★★
()

не секрет а что вы этим хотели добиться?

qnikst ★★★★★
()
Ответ на: комментарий от shuthdar

Сегодня с удивлением для себя открыл полное отсутствие возможности создать abstract private методы в яве.

А зачем?

Inheritance — what your mother never told you

[23.4] When should someone use private virtuals?

When you need to make specific behavior in a base class customizable in derived classes, while protecting the semantics of the interface (and/or the base algorithm therein), which is defined in public methods that call private virtual methods.

Грубо говоря - когда имеется некий метод функционал которого для разных классов отличается в своей незначительной части и поэтому хочется сделать public метод, который будет вызвать небольшой, никому невидимый virtual private метод. Private - потому что я не хочу, чтобы этот кусок метода мог вызвать какой-нибудь другой объект. Abstract - потому что я хочу, чтобы этот небольшой фрагмент кода нужно было явно задавать в каждом наследуемом классе - потому что поведение базового класса «по умолчанию» скорей всего не подошло бы для наследников. Virtual - потому что я хочу, чтобы метод из базового класса вызывал правильный фрагмент кода из наследуемого класса.

Теперь вернемся к Java. В ней все методы virtual. Но я не могу определить abstract private. Как минимум я должен указать abstract protected - но в Java protected имеет совсем другое значение чем в C++. По сути своей protected Java - почти public, так как он по умолчанию доступен всем классам из этого же package.

Comparing C++ and Java

There is no equivalent to the C++ protected keyword which means “accessible to inheritors only” (private protected used to do this, but it was removed).

Вот примерная иллюстрация на C++

#include <iostream>
using namespace std;

class A {
private:
  virtual void f() = 0;
public:
  void testf() {
     cout << "before" << endl;
     f();
     cout << "after" << endl;
  }
};

class AB : public A {
private:
  virtual void f() {
    cout << "test" << endl;
  }
};

int main() {
  (new AB())->testf();
}

testf при этом выступает в роли «как бы декоратора» вокруг метода f.

sign
() автор топика
Ответ на: комментарий от sign

Грубо говоря - когда имеется некий метод функционал которого для разных классов отличается в своей незначительной части и поэтому хочется сделать public метод, который будет вызвать небольшой, никому невидимый virtual private метод. Private - потому что я не хочу, чтобы этот кусок метода мог вызвать какой-нибудь другой объект.

Убивец.

По сути своей protected Java - почти public, так как он по умолчанию доступен всем классам из этого же package.

Вас это беспокоит? Или ты боишься что темной ночью, после 456 серии любимого сериала твой ослабленный самоконтроль сдастся и ты тайно от своего Я, таки, вызовешь этот проклятый протектед метод и ничего уже нельзя будет исправить?

wfrr ★★☆
()
Ответ на: комментарий от Nagwal

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

Как раз abstract virtual private не мешает интанцированию.

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

sign
() автор топика
Ответ на: комментарий от wfrr

> А зачем?

В смысле конкретная задача, которую я решаю и можно ли ее решить другим способом?

Напрямую это с решаемой мной задачей не связано. Меня просто поразил сам факт отсутствия abstract private [virtual] методов в Java. Кстати, кажется, C# в этой части похож на Java и у них тоже нет такой конструкции. Интересно было бы услышать по вышеуказанному вопросу мнение разработчиков C#/Mono.

sign
() автор топика
Ответ на: комментарий от sign

Используй protected. Если ты пишешь какую-то либу, то в твой личный пэкэдж все равно никто не полезет специально цеплять твой скрытый метод - значит в паблик-апи для внешних вызовов его и так и так не будет, а твой пэкэдж - это твой пэкэдж - сам не хочешь цеплять - не цепляй. В яве пэкэдж - это почти архитектурная единица, так что видимость для «своих» классов протэктыд-методов совсем не тоже самое, что паблик; неймспейсы С++'а такого впечатления не оставляют.

bender ★★★★★
()
Ответ на: комментарий от sign

>Как раз abstract virtual private не мешает интанцированию.

Я конечно давное не видел C++, но разве private-методы не должны быть закрыты внутри самого класса - в том числе для классов-наследников? По нормальной логике, смысл делать private-метод виртуальным не имеет смысла, а по логике, описанной в примере, он становится уже не private, а protected.

bender ★★★★★
()
Ответ на: комментарий от sign

Меня просто поразил сам факт отсутствия abstract private [virtual] методов в Java.

А меня поражает отсутсвие reflection в сях, и шо?

wfrr ★★☆
()
Ответ на: комментарий от bender

> Используй protected. Если ты пишешь какую-то либу, то в твой личный пэкэдж все равно никто не полезет специально цеплять твой скрытый метод - значит в паблик-апи для внешних вызовов его и так и так не будет, а твой пэкэдж - это твой пэкэдж - сам не хочешь цеплять - не цепляй.

Согласен, в некоторых случаях это будет удобно. Но, к сожалению, не всегда.

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

В яве пэкэдж - это почти архитектурная единица, так что видимость для «своих» классов протэктыд-методов совсем не тоже самое, что паблик; неймспейсы С++'а такого впечатления не оставляют.

То что java protected <> java public - это понятно. Но вот такого кристально-ясного понимания, что java protected <> c++ protected у меня до сегодняшего дня не было.

sign
() автор топика
Ответ на: комментарий от sign

>> По сути своей protected Java - почти public, так как он по умолчанию доступен всем классам из этого же package.

разве так? всегда казалось, что если не указывать спецификатор видимости, то поле или метод неявно становятся friendly, и с ними можно работать из текущего пакета
а к private вроде и нельзя обращаться, если мы не в том же или в inner классе

note173 ★★★★★
()

В наследнике ты private метод никак не перегрузишь, наследник его не видит, ни для кого, кроме самого класса, private метода не существует. Поэтому конструкция private abstract бессмысленна по сути.

А С++ это совсем другой язык с другими правилами.

Legioner ★★★★★
()
Ответ на: комментарий от sign

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

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

Есть человек А - автор библиотеки, все классы которой находятся в пэкэдже «com.vasya».

И есть человек Б - ипользует библиотеку в своем проекте. Человек Б с 99% вероятности (можно даже говорить о 100%, если речь идет о нормальном проекте, а не каких-то экспериментах) будет использовать пэкэдж «com.petya», точнее не будет использовать пэкэдж «com.vasya» для хранения своих классов. Это буквально означает то, что в своем проекте в нормальной ситуации человек Б-пользователь библиотеки не сможет вызвать ни одного protected-метода из библиотеки авторства человека А кроме как из классов-наследников. Этих более чем достаточно, чтобы конструировать дизайн внешнего API привычным способом на основе private-protected-public.

Просто прими за данность, что область пэкэджа - это область повышенного доверия между классами - т.к. обычно ты сам являешься автором всего того, что находится внутри твоего пэкэджа, то сам лишний раз неправильный метод из неправильного места вызывать не будешь (так же как не будешь без надобности дергать private-метод внутри его класса - сам от себя все равно все инкапсулировать не сможешь). Если класс не хочет скрывать метод от классов вне пэкэджа (при помощи protected), то от родных классов внутри пэкэджа ему уж тем более нечего прятать.

И еще кстати есть 4й модификатор - доступ по дефолту без ключевого слова - такие методы доступны всем классам внутри пэкэджа, но не доступны извне никому (в том числе классам-наследникам).

bender ★★★★★
()

Спеку по языке Жава читать надобно.

Тогда и не будете создавать информационный шум.

Bioreactor ★★★★★
()
Ответ на: комментарий от Bioreactor

> Спеку по языке Жава читать надобно.

Я думаю, что спеку по жаве мало кто осилил. Разве что разработчики спеки и то врядли.

Для создания программ обычно требуется знать практические аспекты применения (чтобы работало) и опытном путем выяснить «как делать не надо». Еще это называется «creative misuse of features».

Тогда и не будете создавать информационный шум.

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

sign
() автор топика
Ответ на: комментарий от note173

По сути своей protected Java - почти public, так как он по умолчанию доступен всем классам из этого же package.

разве так? всегда казалось, что если не указывать спецификатор видимости, то поле или метод неявно становятся friendly, и с ними можно работать из текущего пакета

Я, может быть топорно выразился, сказав «protected Java - почти public», но я не знаю как иначе компактно донести свою мысль.

Вот смотрим таблицу здесь Controlling Access to Members of a Class

Access Levels   Class   Package  Subclass  World
Modifier
public            Y        Y       Y         Y
protected         Y        Y       Y         N
no modifier       Y        Y       N         N
private           Y        N       N         N

Из таблицы наглядно видно, что protected имеет большую область видимости, чем методы «no modifier», и находится по степени доступности на втором месте после public. Именно это я имел в виду, говоря «protected Java - почти public».

а к private вроде и нельзя обращаться, если мы не в том же или в inner классе

Золотые слова - получается что private иногда совсем не private и даже таблица, приведенная по вышеуказанной ссылке вводит нас в заблуждение.

Ведь, если я сделаю внутренний класс, то все его внутренние методы будут доступны - и будет нарушен основной базовый принцип инкапсуляции. Я лишаюсь возможности создавать private методы так, чтобы их никто не мог вызвать за пределами класса.

class Test {

  private static class InnerClass {
    private void internalMethod(int value) {
      if(value == 31337) {
         System.out.println("I am happy :)");
      }
      else {
         System.out.println("You make me cry!");
      }
    }
    void visibleMethod() {
      internalMethod(31337);
    }
  }

  public static void main(String[] args) {
    InnerClass innerClass = new InnerClass(); // say that thrice
    System.out.println("Call visibleMethod");
    innerClass.visibleMethod();
    System.out.println("Call internalMethod");
    innerClass.internalMethod(31337 + 1);
  }

}

А вот и результат

Call visibleMethod
I am happy :)
Call internalMethod
You make me cry!

sign
() автор топика

Спасибо, всем откликнувшимся.

sign
() автор топика
Ответ на: комментарий от sign

для внутренних классов генерируются синтетические поля и методы, что делает private элементы доступными, если я правильно помню

а вот про protected и видимость его для всего пакета не знал
может, его вообще дорисовали, чтобы получить симпатичную треугольную матрицу?)

note173 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.