В Ruby или Python само понятие класса может быть переписано? - PullRequest
9 голосов
/ 23 мая 2010

в первый раз при переполнении стека.

Я изучаю некоторые функции метапрограммирования, предоставляемые Ruby или Python, но сначала мне нужно знать, в какой степени они позволят мне расширить язык,Главное, что мне нужно сделать, это переписать концепцию Class .Это не означает, что я хочу переписать определенный класс во время выполнения, но скорее я хочу сделать свою собственную концептуализацию того, что такое Class .Чтобы быть более конкретным здесь, я хочу сделать что-то, что подобно , что люди обычно называют Классом, но я хочу следовать предположению " открытый мир ".В «закрытом мире» нормальных классов, если я объявлю, что Poodle является подклассом Dog, как подклассом Animal, то я знаю, что Poodle также не будет типом FurCoat.Однако в открытом классе Class объект Poodle, который я определил, может быть или не быть объектом типа FurCoat, и мы не будем знать наверняка, пока я не объясню, что могу носить пуделя.(Бедный пудель.) Это все связано с тем исследованием, которое я проводил в отношении онтологий OWL.

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

Супер спасибо, Джон

ОБНОВЛЕНИЕ: Я только что подумал о хорошем сценарии использования моей концепции Class в открытом мире.Возможно, это даст лучшее понимание того, что я действительно хочу сделать.Я хочу иметь возможность «описывать» класс, а не определять его.Например, я хочу сказать, что Собака - это все, что а) имеет четыре ноги, б) лает.Затем я хочу создать объект неопределенного класса и описать, что этот объект имеет четыре ноги.На данный момент объект все еще имеет неопределенный тип.Тогда я хочу сказать, что объект лает.В этот момент будет известно, что объект (возможно, помимо прочего) - собака.

Ответы [ 5 ]

8 голосов
/ 23 мая 2010

Звучит как утка, набравшая мне .Просто объявите методы, которые вы хотите, и помните, что проще просить прощения, чем разрешения:

try:
    poodle.wear()
except (AttributeError, TypeError):
    pass
7 голосов
/ 23 мая 2010

Я согласен с Самиром в том, что это похоже на утку. Вам не нужно заботиться о том, что «тип» объекта на самом деле является «вам нужно только беспокоиться о том, что объект может« делать ». Это верно как для Ruby, так и для Python.

Однако, если вы действительно проверяете типы классов и вам действительно нужно иметь объект Poodle, опционально также может быть FurCoat во время выполнения, тогда способ сделать это в Ruby - это смешать FurCoat модуль в объект Poodle, как показано ниже:

class Poodle; end
module FurCoat; def wear; end; end

my_poodle = Poodle.new
my_poodle.is_a?(Poodle) #=> true
my_poodle.is_a?(FurCoat) #=> false
my_poodle.wear #=> NoMethodError

# now we mix in the FurCoat module
my_poodle.extend(FurCoat)

# my_poodle is now also a FurCoat
my_poodle.is_a?(Poodle) #=> true (still)
my_poodle.is_a?(FurCoat) #=> true
my_poodle.wear #=> the wear method now works

РЕДАКТИРОВАТЬ (из-за вашего обновленного вопроса):

Вам все еще не нужно переписывать Class для достижения того, что вы хотите, вам просто нужно обезопасить методы kind_of? и is_a? (и, возможно, instance_of?) в модуле Ruby Kernel. Поскольку в Ruby есть открытые классы, это легко сделать:

class Module
    def obj_implements_interface?(obj)
        false
    end
end

module Kernel
    alias_method :orig_is_a?, :is_a?

    def is_a?(klass)
        orig_is_a?(klass) || klass.obj_implements_interface?(self)
    end
end

А затем определите для каждого класса (или модуля), что означает для объекта реализация его интерфейса:

class Dog
    def self.obj_implements_interface?(obj)
        obj.respond_to?(:bark) && obj.respond_to?(:num_legs) && obj.num_legs == 4
    end
end

module FurCoat
    def self.obj_implements_interface?(obj)
        obj.respond_to?(:wear)
    end
end

Теперь проверьте это:

my_poodle = Poodle.new
my_poodle.is_a?(FurCoat) #=> false

# now define a wear method on my_poodle
def my_poodle.wear; end
my_poodle.is_a?(FurCoat) #=> true
6 голосов
/ 23 мая 2010

Нет, вы не можете сделать это в Ruby . В Ruby объектная модель встроена в языковую спецификацию и недоступна (и, конечно, не модифицируемая ) из программы. Даже в Rubinius , который является реализацией Ruby, написанной в основном на Ruby, и с удивительными возможностями метапрограммирования, которые выходят далеко за рамки того, что предлагает спецификация Ruby, некоторые из фундаментальных примитивов встроены в C ++ .

Я не очень хорошо знаком с Python , но я уверен, что так же, даже в PyPy .

Вы могли бы сделать это в Smalltalk , изменив (или подклассифицировав) класс Behavior , который является суперклассом Class и определяет поведение как классов, так и метаклассов.

Вы можете , конечно, сделать это в CLOS или, точнее, используя MOP CLOS ( Meta-Object Protocol ). В конце концов, это то, для чего предназначен MOP: определение объектной модели.

Самая близкая концепция ОО к тому, что вы описываете, это концепция Классов Предикатов . Класс предикатов - это класс, экземпляры которого определяются не статически, а набором предикатов: все объекты, которые удовлетворяют набору предикатов, являются экземплярами класса, как только и так долго, пока держится предикат. В языке с изменяемым состоянием это, очевидно, означает, что объекты могут «входить» и выходить из классов предикатов при изменении их состояния. Это также означает, что в любой момент времени объект может быть экземпляром множества классов предикатов или вообще не иметь их.

Единственный основной язык (для довольно широкого определения «основного потока»), о котором я знаю, имеет классы предикатов: Коэффициент .

Однако обратите внимание, что даже здесь предикаты определены, и объект либо выполняет их, либо не выполняет. Не существует концепции определения того, выполняет ли объект предикат во время выполнения.

Вас также может заинтересовать идея Clojure специальная таксономия .

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

  1. Протоколы
  2. Категория
  3. Взгляд на категории
  4. Нет королей в Риме
  5. Вверх появляется разумное факсимиле
  6. Различные категории категорий
  7. Категории Ошибки
  8. Плоская кошка в чане C3
  9. Категории 0,2
  10. Бард
  11. Бардовские тонкости

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

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

2 голосов
/ 23 мая 2010

В Python вы можете изменить наследование класса во время выполнения, но в каждый момент времени класс не является подклассом другого, если не указано иное. Нет «может или не может» - для этого нужна троичная логика, которую Python не поддерживает. Но, конечно, вы можете написать свои собственные функции "Is-a" и "Has-a" для отображения онтологий OWL на классы Python.

1 голос
/ 23 мая 2010

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

Классы, служащие в качестве шаблонов, и объекты, выступающие в качестве экземпляров, не дают абсолютно никаких преимуществ при использованиис OWA.Рассмотрим класс Person, где мы кодируем знание, что у человека есть 2 ноги.Тем не менее, мы не можем сделать вывод, что у человека будет две ноги, так как у человека может быть инвалидность.

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

...