final class (Java)

Компьютеры. программирование, бытовая техника

Модератор: Саша З.

Аватара пользователя
alexsmail
Ветеран мега-форума
Сообщения: 12637
Зарегистрирован(а): 28 дек 2004, 21:49
Откуда: Мединат hаеhудим
Контактная информация:

final class (Java)

Сообщение alexsmail » 14 май 2005, 21:52

У меня такой вопрос. У меня есть класс, у которого все конструкторы private. Зачем делать класс final?
Я встречал такое объясение:

It"s a final class with a private constructor so no one can inherit from it or make any instances of it.

Но почему private constructor недостаточно?

Пример:

public class Color {
private Color(){}

public static final Color BLUE=new Color();
public static final Color RED=new Color();
}

Зачем менять декларацию класса на
public final class Color?

Ведь следующий код работать всё равно не будет

public class SuperColor extends Color {
public SuperColor(){
//super();
}
}

Так как неявно будет сделана попытка вызвать конструктор суперкласса, а сделать это невозможно. Это compile-time error. Или всё таки есть какой-то обходной путь?[/b]
Мой блог http://toalexsmail.com/

Лучшее - враг хорошего.

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

Нужно воспитывать опрятность в мышлении.

dba_netanya
Участник форума
Сообщения: 134
Зарегистрирован(а): 11 июл 2002, 13:14
Откуда: Ramat Gan, Israel
Контактная информация:

Сообщение dba_netanya » 14 май 2005, 22:06

Рихтер пишет (.NET), что если Вы хотите Abstract Sealed class:
Because CLR doesn't support this marking (Abstract Sealed), if you are designing your own type, you should mark the type as Sealed and define a private parameterless constructor that is never called.
"A successful person is one who can lay a firm foundation with the bricks that others throw at him."

Аватара пользователя
Зяма Крендель
Ветеран мега-форума
Сообщения: 5327
Зарегистрирован(а): 21 июл 2003, 13:07
Откуда: Чикаго

Сообщение Зяма Крендель » 14 май 2005, 22:09

alexsmail, я бы сказал, чтобы сделать назначение класса более явным.

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

С другой стороны, такое наследование также ничего не даёт, поскольку, как известно, статические методы наследоваться не могут в приниципе, а другие в таком случае бесполезны.
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении

Аватара пользователя
alexsmail
Ветеран мега-форума
Сообщения: 12637
Зарегистрирован(а): 28 дек 2004, 21:49
Откуда: Мединат hаеhудим
Контактная информация:

Сообщение alexsmail » 15 май 2005, 05:38

dba_netanya писал(а):Рихтер пишет (.NET), что если Вы хотите Abstract Sealed class:
Because CLR doesn't support this marking (Abstract Sealed), if you are designing your own type, you should mark the type as Sealed and define a private parameterless constructor that is never called.

dba_netanya, не понял я ответа.

Зяма Крендель писал(а):alexsmail, я бы сказал, чтобы сделать назначение класса более явным.


Эта причина понятна. Плюс ещё компилятор сможет сделать оптимизации.

Зяма Крендель писал(а):Но вообще, все конструкторы private делают для того, чтобы класс был не для инстанциации - иными словами, когда пользоваться можно только статическими элементами класса.


Далеко не так. В приведённому мной примере можно пользоваться, например, Color.Blue. Это обычный объект. Если в классе Color есть обычные instance method, то их можно будет запускать через него. Другой пример, design pattern Singleton.


Зяма Крендель писал(а):В принципе, наследование такого класса никаких особых правил не нарушает, покуда и наследующий класс не предназначается для инстанциации - т.е. у него тоже пользоваться можно будет только статическими элементами.

Наследующий класс задать нельзя, насколько я вижу из-за приведеного в первом посте факта. Хотя тут, возможно, я ошибаюсь. Дело в том, что у любого есть default contructor. Если программист не задаёт его явно, то он неявно добавляется. В любом конструкторе, первоая строчка которог не super(...) и не this(...) неявным образом добавляется строчка super(), т.е. вызов default super contructor. Неявным образом добавленый конструктор иммет тоже вид:
(public) SuperColor(){
super();
}

Идентификатор этого конструктора, такой же как и у класса. Например, если класс объявлен public, то и конструктор будет public.
Насчет не нарушение особых правил. Все дело в том, что я не хочу, чтобы пользователи моиего класса инстанциировали мой объект. Если дать возможность определить superclass, то это станет возможным, так как SuperColor он также типа Color. Строчка типа
Color c = new SuperColor();

станет возможной.


Зяма Крендель писал(а):С другой стороны, такое наследование также ничего не даёт, поскольку, как известно, статические методы наследоваться не могут в приниципе, а другие в таком случае бесполезны.

Это неверно в свете вышеперечисленного.


Итак найдены 2 причины:
1) сделать назначение класса более явным.
2) компилятор сможет сделать оптимизации.

Но есть ли другие причины? Есть ли обходной путь создания SuperColor?

* edited: * я знаю 2 обходных пути создания нового интсанса класса. Но декларировния класса final, не мешают мне ими воспользоваться.
Мой блог http://toalexsmail.com/

Лучшее - враг хорошего.

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

Нужно воспитывать опрятность в мышлении.

Аватара пользователя
Зяма Крендель
Ветеран мега-форума
Сообщения: 5327
Зарегистрирован(а): 21 июл 2003, 13:07
Откуда: Чикаго

Сообщение Зяма Крендель » 15 май 2005, 15:13

alexsmail писал(а):
Зяма Крендель писал(а):alexsmail, я бы сказал, чтобы сделать назначение класса более явным.

Эта причина понятна. Плюс ещё компилятор сможет сделать оптимизации.

Согласен.


alexsmail писал(а):
Зяма Крендель писал(а):Но вообще, все конструкторы private делают для того, чтобы класс был не для инстанциации - иными словами, когда пользоваться можно только статическими элементами класса.

Далеко не так. В приведённому мной примере можно пользоваться, например, Color.Blue. Это обычный объект. Если в классе Color есть обычные instance method, то их можно будет запускать через него. Другой пример, design pattern Singleton.

Согласен просто забыл про них сказать. А метода "getInstance" в вашем примере не было. :ic1:


alexsmail писал(а):
Зяма Крендель писал(а):В принципе, наследование такого класса никаких особых правил не нарушает, покуда и наследующий класс не предназначается для инстанциации - т.е. у него тоже пользоваться можно будет только статическими элементами.

Наследующий класс задать нельзя, насколько я вижу из-за приведеного в первом посте факта. Хотя тут, возможно, я ошибаюсь. Дело в том, что у любого есть default contructor. Если программист не задаёт его явно, то он неявно добавляется. В любом конструкторе, первоая строчка которог не super(...) и не this(...) неявным образом добавляется строчка super(), т.е. вызов default super contructor. Неявным образом добавленый конструктор иммет тоже вид:
(public) SuperColor(){
super();
}

Разумеется. Но почему это воспрепятствует объявлению наследующего класса?.. Вот его инстанциации - да!


alexsmail писал(а):Идентификатор этого конструктора, такой же как и у класса. Например, если класс объявлен public, то и конструктор будет public.

Не понял... а если класс default, то и конструктор default?.. :13:


alexsmail писал(а):Насчет не нарушение особых правил. Все дело в том, что я не хочу, чтобы пользователи моиего класса инстанциировали мой объект. Если дать возможность определить superclass, то это станет возможным, так как SuperColor он также типа Color. Строчка типа
Color c = new SuperColor();

станет возможной.

Если у изначального класса все конструкторы private, то на этой строчке будет compilе time error.


Кстати, вы, очевидно, имели в виду subclass - superclass для готового класса определить невозможно ;)
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении

AlexZ75
Участник со стажем
Сообщения: 1304
Зарегистрирован(а): 18 ноя 2001, 02:00
Откуда: Петах-Тиква
Контактная информация:

Сообщение AlexZ75 » 15 май 2005, 18:44

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

Код: Выделить всё

class SubColor extends Color{
public static instance=null
    private SubColor(){



     }
    public static SubColor getInstance(){
          if (instance==null) instance=new SubColor();
          return instance;

   }


}

Соответвенно final что бы не дать наследовать.
Обойти это можно, если есть удобоворимый предок либо писать криво:

Код: Выделить всё

Object c...
if (c instanceOf) Color {
        (Color) c

} elseif (c instanceOf SupColor){
   (SupColor)  c
}
Отличительная черта большинства туземцев - человеколюбие.

Аватара пользователя
alexsmail
Ветеран мега-форума
Сообщения: 12637
Зарегистрирован(а): 28 дек 2004, 21:49
Откуда: Мединат hаеhудим
Контактная информация:

Сообщение alexsmail » 15 май 2005, 21:34

alexsmail писал(а):
Зяма Крендель писал(а):В принципе, наследование такого класса никаких особых правил не нарушает, покуда и наследующий класс не предназначается для инстанциации - т.е. у него тоже пользоваться можно будет только статическими элементами.

Наследующий класс задать нельзя, насколько я вижу из-за приведеного в первом посте факта. Хотя тут, возможно, я ошибаюсь. Дело в том, что у любого есть default contructor. Если программист не задаёт его явно, то он неявно добавляется. В любом конструкторе, первоая строчка которог не super(...) и не this(...) неявным образом добавляется строчка super(), т.е. вызов default super contructor. Неявным образом добавленый конструктор иммет тоже вид:
(public) SuperColor(){
super();
}

Разумеется. Но почему это воспрепятствует объявлению наследующего класса?.. Вот его инстанциации - да!

Мой компилятор ругается.

alexsmail писал(а):Идентификатор этого конструктора, такой же как и у класса. Например, если класс объявлен public, то и конструктор будет public.


Не понял... а если класс default, то и конструктор default?.. :13:


Да.
alexsmail писал(а):Насчет не нарушение особых правил. Все дело в том, что я не хочу, чтобы пользователи моиего класса инстанциировали мой объект. Если дать возможность определить superclass, то это станет возможным, так как SuperColor он также типа Color. Строчка типа
Color c = new SuperColor();

станет возможной.


Если у изначального класса все конструкторы private, то на этой строчке будет compilе time error.


compilе time error будет намного раньше.

Кстати, вы, очевидно, имели в виду subclass - superclass для готового класса определить невозможно ;)

У меня просто SuperColor это в смысле "крутой" (хитрый) Color. Неудачное имя, согласен. Это действительно subclass .
Мой блог http://toalexsmail.com/

Лучшее - враг хорошего.

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

Нужно воспитывать опрятность в мышлении.

Аватара пользователя
alexsmail
Ветеран мега-форума
Сообщения: 12637
Зарегистрирован(а): 28 дек 2004, 21:49
Откуда: Мединат hаеhудим
Контактная информация:

Сообщение alexsmail » 15 май 2005, 21:46

AlexZ75 писал(а):alexsmail,
Очень часто делают конструкторы приватными чтобы не дать явно создавать экземпляры классов...
Соответвенно final что бы не дать наследовать.


Видимо я чего-то таки недопонимаю.

Код: Выделить всё

class SubColor extends Color{
public static [b]SubColor[/b] instance=null;
    private SubColor(){
     }
    public static SubColor getInstance(){
          if (instance==null) instance=new SubColor();
          return instance;

   }


}


Вы забыли указать тип.
Конструктор SubColor эквивалентен следующему

Код: Выделить всё

private SubColor(){
super();
}
   


Так вот, вызвать super() невозможно, так как это конструктор он private!
Мой компилятор уже при попытке декларации SubColor выдаёт ошибку, что он не сможет запустить <init> Color (defalut constructor Color).

Обойти это можно, если есть удобоворимый предок либо писать криво:

Код: Выделить всё

Object c...
if (c instanceOf) Color {
        (Color) c

} elseif (c instanceOf SupColor){
   (SupColor)  c
}


Не понимаю :13:
Мой блог http://toalexsmail.com/

Лучшее - враг хорошего.

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

Нужно воспитывать опрятность в мышлении.

Аватара пользователя
Зяма Крендель
Ветеран мега-форума
Сообщения: 5327
Зарегистрирован(а): 21 июл 2003, 13:07
Откуда: Чикаго

Сообщение Зяма Крендель » 15 май 2005, 21:57

alexsmail, а что такое элемент класса с доступом default??.. :13: :13:

Насчёт остального - я это просто попробую сам (при первой возможности) и сразу напишу... Мне самому интересно.
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении

Аватара пользователя
Зяма Крендель
Ветеран мега-форума
Сообщения: 5327
Зарегистрирован(а): 21 июл 2003, 13:07
Откуда: Чикаго

Сообщение Зяма Крендель » 15 май 2005, 21:59

AlexZ75, это когда экземпляры класса уже созданы. Мы говорим о принципиальной возможности их создавать.
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении

Аватара пользователя
alexsmail
Ветеран мега-форума
Сообщения: 12637
Зарегистрирован(а): 28 дек 2004, 21:49
Откуда: Мединат hаеhудим
Контактная информация:

Сообщение alexsmail » 16 май 2005, 00:11

Зяма Крендель писал(а):alexsmail, а что такое элемент класса с доступом default??.. :13: :13:


Другое его название это package protected. К такому элементу класса имеют доступ только классы, находящееся с этим классом в одном пакете.

Sun писал(а):whether classes in the same package as the class (regardless of their parentage) have access to the member.


Зяма Крендель писал(а):Насчёт остального - я это просто попробую сам (при первой возможности) и сразу напишу... Мне самому интересно.

Рад, что заинтересовал. :)
Мой блог http://toalexsmail.com/

Лучшее - враг хорошего.

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

Нужно воспитывать опрятность в мышлении.

Аватара пользователя
Зяма Крендель
Ветеран мега-форума
Сообщения: 5327
Зарегистрирован(а): 21 июл 2003, 13:07
Откуда: Чикаго

Сообщение Зяма Крендель » 16 май 2005, 01:11

alexsmail, ага, точно-точно... спасибо.
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении

Аватара пользователя
Зяма Крендель
Ветеран мега-форума
Сообщения: 5327
Зарегистрирован(а): 21 июл 2003, 13:07
Откуда: Чикаго

Сообщение Зяма Крендель » 16 май 2005, 10:30

Хмм... по некотором размышлении понял, что не очень понимаю смысл этого правила: "Идентификатор этого конструктора, такой же как и у класса. Например, если класс объявлен public, то и конструктор будет public." Допустим класс public - так конструктор просто практически бессмысленно делать другим, кроме как public - класс нельзя будет инстанциировать за пределами package. Наоборот ещё хуже...
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении

Аватара пользователя
Yura2000
Участник со стажем
Сообщения: 204
Зарегистрирован(а): 12 май 2004, 17:20

Сообщение Yura2000 » 16 май 2005, 10:38

Вooбсче-тo если дaже клaсс с кoнструктoрaми private нет у меня прoблемы пoднятъ егo инстaнс ( в .NET)
Никогда нельзя в такой полной мере терять моральный облик, чтобы хвалить полицию.

Аватара пользователя
Зяма Крендель
Ветеран мега-форума
Сообщения: 5327
Зарегистрирован(а): 21 июл 2003, 13:07
Откуда: Чикаго

Сообщение Зяма Крендель » 16 май 2005, 13:12

OK, попробовал. Да, Java, в отличие от C++ (на котором я работал последние неск. лет :37: ), такое запрещает. Наверно, потому, что такой класс не получится инстанциировать вообще никак, так что остаются статические методы, а для них не нужно наследование. :ic1:
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении

dba_netanya
Участник форума
Сообщения: 134
Зарегистрирован(а): 11 июл 2002, 13:14
Откуда: Ramat Gan, Israel
Контактная информация:

Сообщение dba_netanya » 16 май 2005, 20:29

Yura2000 писал(а):Вooбсче-тo если дaже клaсс с кoнструктoрaми private нет у меня прoблемы пoднятъ егo инстaнс ( в .NET)

Вы имеете ввиду, что если нет ни одного public constructor, то можно создать инстанс в .NET?
Как?
"A successful person is one who can lay a firm foundation with the bricks that others throw at him."

Аватара пользователя
DK
Ветеран мега-форума
Сообщения: 9049
Зарегистрирован(а): 02 май 2002, 12:18
Откуда: Израиль

Сообщение DK » 16 май 2005, 21:37

На Джаве не писал, но на С++ нет никаких проблем инстанциировать класс с private конструкторами для френдов. Френд также может отнаследовать от такого класса - т.е. наследник и есть френд.

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

Аватара пользователя
Зяма Крендель
Ветеран мега-форума
Сообщения: 5327
Зарегистрирован(а): 21 июл 2003, 13:07
Откуда: Чикаго

Сообщение Зяма Крендель » 17 май 2005, 10:40

DK, :44:

Но вообще, сравнивать C++ и Java - неблагодарное дело... И всё равно ничего не изменит... к сожалению! :37:
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении

AlexZ75
Участник со стажем
Сообщения: 1304
Зарегистрирован(а): 18 ноя 2001, 02:00
Откуда: Петах-Тиква
Контактная информация:

Сообщение AlexZ75 » 17 май 2005, 12:24

DK,
Если класс final ты не можешь сделать наследнование от него, никаким образом. Френдов в java нет.
Отличительная черта большинства туземцев - человеколюбие.

Аватара пользователя
Зяма Крендель
Ветеран мега-форума
Сообщения: 5327
Зарегистрирован(а): 21 июл 2003, 13:07
Откуда: Чикаго

Сообщение Зяма Крендель » 17 май 2005, 12:58

AlexZ75, а в C++ и final тоже нет. И они там даже не особо нужны - в C++ функции по умолчанию НЕ виртуальные. А сделать класс таким, чтобы его нельзя было наследовать - упражнение такое (больше прикольное, чем практическое), его хорошо на интервью давать. :37:
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении


Вернуться в «Наука и техника»




  Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 11 гостей