final class (Java)
Модератор: Саша З.
- alexsmail
- Ветеран мега-форума
- Сообщения: 12637
- Зарегистрирован(а): 28 дек 2004, 21:49
- Откуда: Мединат hаеhудим
- Контактная информация:
final class (Java)
У меня такой вопрос. У меня есть класс, у которого все конструкторы 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]
Я встречал такое объясение:
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/
Лучшее - враг хорошего.
Великие умы обсуждают идеи, посредственные умы обсуждают события, недалекие умы обсуждают личности. Элеонора Рузвельт
Нужно воспитывать опрятность в мышлении.
Лучшее - враг хорошего.
Великие умы обсуждают идеи, посредственные умы обсуждают события, недалекие умы обсуждают личности. Элеонора Рузвельт
Нужно воспитывать опрятность в мышлении.
-
- Участник форума
- Сообщения: 134
- Зарегистрирован(а): 11 июл 2002, 13:14
- Откуда: Ramat Gan, Israel
- Контактная информация:
Рихтер пишет (.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.
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
- Откуда: Чикаго
alexsmail, я бы сказал, чтобы сделать назначение класса более явным.
Но вообще, все конструкторы private делают для того, чтобы класс был не для инстанциации - иными словами, когда пользоваться можно только статическими элементами класса. В принципе, наследование такого класса никаких особых правил не нарушает, покуда и наследующий класс не предназначается для инстанциации - т.е. у него тоже пользоваться можно будет только статическими элементами.
С другой стороны, такое наследование также ничего не даёт, поскольку, как известно, статические методы наследоваться не могут в приниципе, а другие в таком случае бесполезны.
Но вообще, все конструкторы private делают для того, чтобы класс был не для инстанциации - иными словами, когда пользоваться можно только статическими элементами класса. В принципе, наследование такого класса никаких особых правил не нарушает, покуда и наследующий класс не предназначается для инстанциации - т.е. у него тоже пользоваться можно будет только статическими элементами.
С другой стороны, такое наследование также ничего не даёт, поскольку, как известно, статические методы наследоваться не могут в приниципе, а другие в таком случае бесполезны.
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении
© Учебник психиатрии, симптомы шизофрении
- alexsmail
- Ветеран мега-форума
- Сообщения: 12637
- Зарегистрирован(а): 28 дек 2004, 21:49
- Откуда: Мединат hаеhудим
- Контактная информация:
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
- Откуда: Чикаго
alexsmail писал(а):Зяма Крендель писал(а):alexsmail, я бы сказал, чтобы сделать назначение класса более явным.
Эта причина понятна. Плюс ещё компилятор сможет сделать оптимизации.
Согласен.
alexsmail писал(а):Зяма Крендель писал(а):Но вообще, все конструкторы private делают для того, чтобы класс был не для инстанциации - иными словами, когда пользоваться можно только статическими элементами класса.
Далеко не так. В приведённому мной примере можно пользоваться, например, Color.Blue. Это обычный объект. Если в классе Color есть обычные instance method, то их можно будет запускать через него. Другой пример, design pattern Singleton.
Согласен просто забыл про них сказать. А метода "getInstance" в вашем примере не было.
alexsmail писал(а):Зяма Крендель писал(а):В принципе, наследование такого класса никаких особых правил не нарушает, покуда и наследующий класс не предназначается для инстанциации - т.е. у него тоже пользоваться можно будет только статическими элементами.
Наследующий класс задать нельзя, насколько я вижу из-за приведеного в первом посте факта. Хотя тут, возможно, я ошибаюсь. Дело в том, что у любого есть default contructor. Если программист не задаёт его явно, то он неявно добавляется. В любом конструкторе, первоая строчка которог не super(...) и не this(...) неявным образом добавляется строчка super(), т.е. вызов default super contructor. Неявным образом добавленый конструктор иммет тоже вид:
(public) SuperColor(){
super();
}
Разумеется. Но почему это воспрепятствует объявлению наследующего класса?.. Вот его инстанциации - да!
alexsmail писал(а):Идентификатор этого конструктора, такой же как и у класса. Например, если класс объявлен public, то и конструктор будет public.
Не понял... а если класс default, то и конструктор default?..
alexsmail писал(а):Насчет не нарушение особых правил. Все дело в том, что я не хочу, чтобы пользователи моиего класса инстанциировали мой объект. Если дать возможность определить superclass, то это станет возможным, так как SuperColor он также типа Color. Строчка типа
Color c = new SuperColor();
станет возможной.
Если у изначального класса все конструкторы private, то на этой строчке будет compilе time error.
Кстати, вы, очевидно, имели в виду subclass - superclass для готового класса определить невозможно
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении
© Учебник психиатрии, симптомы шизофрении
-
- Участник со стажем
- Сообщения: 1304
- Зарегистрирован(а): 18 ноя 2001, 02:00
- Откуда: Петах-Тиква
- Контактная информация:
alexsmail,
Очень часто делают конструкторы приватными чтобы не дать явно создавать экземпляры классов, например в сиглетонах:
Соответвенно final что бы не дать наследовать.
Обойти это можно, если есть удобоворимый предок либо писать криво:
Очень часто делают конструкторы приватными чтобы не дать явно создавать экземпляры классов, например в сиглетонах:
Код: Выделить всё
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 писал(а):Зяма Крендель писал(а):В принципе, наследование такого класса никаких особых правил не нарушает, покуда и наследующий класс не предназначается для инстанциации - т.е. у него тоже пользоваться можно будет только статическими элементами.
Наследующий класс задать нельзя, насколько я вижу из-за приведеного в первом посте факта. Хотя тут, возможно, я ошибаюсь. Дело в том, что у любого есть default contructor. Если программист не задаёт его явно, то он неявно добавляется. В любом конструкторе, первоая строчка которог не super(...) и не this(...) неявным образом добавляется строчка super(), т.е. вызов default super contructor. Неявным образом добавленый конструктор иммет тоже вид:
(public) SuperColor(){
super();
}
Разумеется. Но почему это воспрепятствует объявлению наследующего класса?.. Вот его инстанциации - да!
Мой компилятор ругается.
alexsmail писал(а):Идентификатор этого конструктора, такой же как и у класса. Например, если класс объявлен public, то и конструктор будет public.
Не понял... а если класс default, то и конструктор default?..
Да.
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удим
- Контактная информация:
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
}
Не понимаю
Мой блог http://toalexsmail.com/
Лучшее - враг хорошего.
Великие умы обсуждают идеи, посредственные умы обсуждают события, недалекие умы обсуждают личности. Элеонора Рузвельт
Нужно воспитывать опрятность в мышлении.
Лучшее - враг хорошего.
Великие умы обсуждают идеи, посредственные умы обсуждают события, недалекие умы обсуждают личности. Элеонора Рузвельт
Нужно воспитывать опрятность в мышлении.
- Зяма Крендель
- Ветеран мега-форума
- Сообщения: 5327
- Зарегистрирован(а): 21 июл 2003, 13:07
- Откуда: Чикаго
alexsmail, а что такое элемент класса с доступом default??..
Насчёт остального - я это просто попробую сам (при первой возможности) и сразу напишу... Мне самому интересно.
Насчёт остального - я это просто попробую сам (при первой возможности) и сразу напишу... Мне самому интересно.
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении
© Учебник психиатрии, симптомы шизофрении
- Зяма Крендель
- Ветеран мега-форума
- Сообщения: 5327
- Зарегистрирован(а): 21 июл 2003, 13:07
- Откуда: Чикаго
- alexsmail
- Ветеран мега-форума
- Сообщения: 12637
- Зарегистрирован(а): 28 дек 2004, 21:49
- Откуда: Мединат hаеhудим
- Контактная информация:
Зяма Крендель писал(а):alexsmail, а что такое элемент класса с доступом default??..
Другое его название это 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
- Откуда: Чикаго
- Зяма Крендель
- Ветеран мега-форума
- Сообщения: 5327
- Зарегистрирован(а): 21 июл 2003, 13:07
- Откуда: Чикаго
Хмм... по некотором размышлении понял, что не очень понимаю смысл этого правила: "Идентификатор этого конструктора, такой же как и у класса. Например, если класс объявлен public, то и конструктор будет public." Допустим класс public - так конструктор просто практически бессмысленно делать другим, кроме как public - класс нельзя будет инстанциировать за пределами package. Наоборот ещё хуже...
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении
© Учебник психиатрии, симптомы шизофрении
- Зяма Крендель
- Ветеран мега-форума
- Сообщения: 5327
- Зарегистрирован(а): 21 июл 2003, 13:07
- Откуда: Чикаго
OK, попробовал. Да, Java, в отличие от C++ (на котором я работал последние неск. лет ), такое запрещает. Наверно, потому, что такой класс не получится инстанциировать вообще никак, так что остаются статические методы, а для них не нужно наследование.
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении
© Учебник психиатрии, симптомы шизофрении
-
- Участник форума
- Сообщения: 134
- Зарегистрирован(а): 11 июл 2002, 13:14
- Откуда: Ramat Gan, Israel
- Контактная информация:
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."
На Джаве не писал, но на С++ нет никаких проблем инстанциировать класс с private конструкторами для френдов. Френд также может отнаследовать от такого класса - т.е. наследник и есть френд.
Я лично пользовался такой техникой для создания внутренних классов. Это удобно, чтобы не создавать слишком глубокой визуальной вложенности деклараций и для служебных классов, пользование которыми должно быть строго локализовано внутри ограниченного кол-ва других классов.
Я лично пользовался такой техникой для создания внутренних классов. Это удобно, чтобы не создавать слишком глубокой визуальной вложенности деклараций и для служебных классов, пользование которыми должно быть строго локализовано внутри ограниченного кол-ва других классов.
- Зяма Крендель
- Ветеран мега-форума
- Сообщения: 5327
- Зарегистрирован(а): 21 июл 2003, 13:07
- Откуда: Чикаго
- Зяма Крендель
- Ветеран мега-форума
- Сообщения: 5327
- Зарегистрирован(а): 21 июл 2003, 13:07
- Откуда: Чикаго
AlexZ75, а в C++ и final тоже нет. И они там даже не особо нужны - в C++ функции по умолчанию НЕ виртуальные. А сделать класс таким, чтобы его нельзя было наследовать - упражнение такое (больше прикольное, чем практическое), его хорошо на интервью давать.
"...читает недоступную его пониманию философскую литературу, делает бессистемные выписки..."
© Учебник психиатрии, симптомы шизофрении
© Учебник психиатрии, симптомы шизофрении
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 31 гость