Почему объектные объекты более объектно-ориентированные?

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

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

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

Ответ 1

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

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

  • Статические элементы не могут быть унаследованы от родительского класса/признака
  • Статические элементы не могут использоваться для реализации интерфейса
  • Статические члены класса не могут передаваться в качестве аргумента некоторой функции

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

  • Статические элементы нельзя переопределить
  • Статические элементы не могут быть полиморфными

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

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


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

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

Ответ 2

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

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

Ответ 3

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

Серьезно.

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

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

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

Ответ 4

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

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

Честно говоря, он раскалывает волосы.

Ответ 5

Более объектно ориентированный в том смысле, что данный класс 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()
  }
}

Ответ 6

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

Ответ 7

Это действительно маркетинговая штука. Рассмотрим два примера:

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 лет назад о том, действительно ли С++ или Java были "реально" объектно-ориентированными, поскольку ведь обе обнаженные примитивные типы, которые не являются "действительно" объектами, - так, например, вы не можете наследует от int, но может от Integer.