Почему одноэлементные объекты более объектно-ориентированы? - PullRequest
35 голосов
/ 06 ноября 2010

In Программирование в Scala: подробное пошаговое руководство , автор сказал:

Один из способов, которым Scala является более объектно-ориентированным, чем Java, заключается в том, чтоклассы в Scala не могут иметь статических членов.Вместо этого в Scala есть одноэлементные объекты.

Почему объект singleton является более объектно-ориентированным?Какая польза не от использования статических элементов, а от одноэлементных объектов?

Ответы [ 7 ]

58 голосов
/ 06 ноября 2010

Попытка «большой картинки»;большая часть этого была рассмотрена в других ответах, но, похоже, не существует ни одного всеобъемлющего ответа, который бы объединял все это и объединял точки.Итак, здесь ...

Статические методы в классе не являются методами для объекта, это означает, что:

  1. Статические члены не могут быть унаследованы от родительского класса / признака
  2. Статические члены не могут использоваться для реализации интерфейса
  3. Статические члены класса не могут быть переданы в качестве аргумента какой-либо функции

    (и из-за вышеуказанных пунктов ...)

  4. Статические члены не могут быть переопределены
  5. Статические члены не могут быть полиморфными

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

Синглтон-объекты, с другой стороны, являются полноправными членами объектного сообщества.


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

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

12 голосов
/ 06 ноября 2010

Объекты Singleton ведут себя как классы в том смысле, что они могут расширять / реализовывать другие типы.

Невозможно сделать это в Java только с помощью статических классов - это довольно сахар над шаблоном синглтона Java с getInstance, который позволяет (по крайней мере) более хорошие пространства имен / стабильные идентификаторы и скрывают различия.

10 голосов
/ 06 ноября 2010

Подсказка: это называется объект -ориентированное программирование.

Серьезно.

Может быть, я упускаю что-то принципиально важное, но я не понимаю, в чем суетавсе о: объекты более объектно-ориентированы, чем не-объекты, потому что они являются объектами.Это действительно нуждается в объяснении?

Примечание: Хотя это звучит так, я действительно не пытаюсь звучать самодовольно.Я посмотрел на все остальные ответы и нашел их ужасно запутанными.Для меня очевидно, что объекты и методы более объектно-ориентированы, чем пространства имен и процедуры (что на самом деле представляют собой статические "методы") по самому определению"объектно-ориентированного".

Альтернативой наличию одноэлементных объектов может быть создание самими классами объектов, как, например, делают Ruby, Python, Smalltalk, Newspeak.

2 голосов
/ 06 ноября 2010

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

2 голосов
/ 06 ноября 2010

Он более объектно-ориентирован в том смысле, что для данного класса Scala каждый вызов метода является вызовом метода для этого объекта.В Java статические методы не взаимодействуют с состоянием объекта.

Фактически, учитывая объект a класса A со статическим методом m(), вызывать вызовы считается плохой практикой.a.m().Вместо этого рекомендуется позвонить A.m() (я полагаю, Eclipse предупредит вас).Статические методы Java не могут быть переопределены, они могут быть просто скрыты другим методом:

class A {
    public static void m() {
        System.out.println("m from A");
    }
}
public class B extends A {
    public static void m() {
        System.out.println("m from B");
    }
    public static void main(String[] args) {
        A a = new B();
        a.m();
    }
}

Что будет печатать a.m()?

В Scala вы вставляете статические методы в объекты-компаньоны A и B, и намерение будет более ясным, как если бы вы явно ссылались на компаньона A или B.Scala:

class A
object A { 
  def m() = println("m from A") 
}
class B extends A
object B { 
  def m() = println("m from B")
  def main(args: Array[String]) {
    val a = new B
    A.m() // cannot call a.m()
  }
}
2 голосов
/ 06 ноября 2010

Для статических элементов объект отсутствует.Класс на самом деле просто является пространством имен.

В синглтоне всегда есть хотя бы один объект.

Честно говоря, это расщепление волос.

0 голосов
/ 06 ноября 2010

Это маркетинговая вещь, правда. Рассмотрим два примера:

class foo
   static const int bar = 42;
end class

class superfoo
    Integer bar = ConstInteger.new(42);
end class

Теперь, какие здесь наблюдаемые различия?

  • на хорошем языке, дополнительное хранилище остается тем же.
  • Foo.bar и Superfoo.bar имеют абсолютно одинаковые подписи, доступ и т. Д.
  • Superfoo.bar может быть выделен по-другому, но это деталь реализации

Это напоминает мне о религиозных войнах 20 лет назад из-за того, были ли C ++ или Java «действительно» объектно-ориентированными, поскольку в конце концов оба открытых примитивных типа не являются «настоящими» объектами - так, например, вы не можете наследовать от int, но может от Integer.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...