Как реализовать абстрактный класс в рубине?

используйте $file->getClientOriginalExtension() в коде, если вы хотите проверить только расширение файла

$ext = $file->getClientOriginalExtension();
if($ext == 'ico'){
  //uploadfile
}else{
  //do something else
}

, используйте этот в качестве ссылки.

113
задан andrewdotn 6 March 2016 в 02:06
поделиться

10 ответов

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

module Abstract
  def abstract_methods(*args)
    args.each do |name|
      class_eval(<<-END, __FILE__, __LINE__)
        def #{name}(*args)
          raise NotImplementedError.new("You must implement #{name}.")
        end
      END
      # important that this END is capitalized, since it marks the end of <<-END
    end
  end
end

require 'rubygems'
require 'rspec'

describe "abstract methods" do
  before(:each) do
    @klass = Class.new do
      extend Abstract

      abstract_methods :foo, :bar
    end
  end

  it "raises NoMethodError" do
    proc {
      @klass.new.foo
    }.should raise_error(NoMethodError)
  end

  it "can be overridden" do
    subclass = Class.new(@klass) do
      def foo
        :overridden
      end
    end

    subclass.new.foo.should == :overridden
  end
end

В основном, Вы просто звоните abstract_methods со списком методов, которые абстрактны, и когда их назовет экземпляр абстрактного класса, NotImplementedError, исключение будет повышено.

57
ответ дан Magne 24 November 2019 в 02:40
поделиться

Другой ответ:

module Abstract
  def self.append_features(klass)
    # access an object's copy of its class's methods & such
    metaclass = lambda { |obj| class << obj; self ; end }

    metaclass[klass].instance_eval do
      old_new = instance_method(:new)
      undef_method :new

      define_method(:inherited) do |subklass|
        metaclass[subklass].instance_eval do
          define_method(:new, old_new)
        end
      end
    end
  end
end

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

class A
  include Abstract
end
class B < A
end

B.new #=> #<B:0x24ea0>
A.new # raises #<NoMethodError: undefined method `new' for A:Class>

Как другие плакаты, сказали, необходимо, вероятно, использовать смешивание хотя, а не абстрактный класс.

3
ответ дан rampion 24 November 2019 в 02:40
поделиться

Ничто неправильно с Вашим подходом. Повысьте ошибку в, инициализируют, кажется прекрасным, пока все Ваше переопределение подклассов инициализирует, конечно. Но Вы не хотите определять self.new как этот. Вот то, что я сделал бы.

class A
  class AbstractClassInstiationError < RuntimeError; end
  def initialize
    raise AbstractClassInstiationError, "Cannot instantiate this class directly, etc..."
  end
end

Другой подход был бы помещен вся эта функциональность в модуле, который, поскольку Вы упомянули, никогда не может быть instiated. Затем включайте модуль в свои классы вместо того, чтобы наследоваться другому классу. Однако это повредило бы вещи как супер.

, Таким образом, это зависит от того, как Вы хотите структурировать его. Хотя модули походят на более чистое решение для решения проблемы, "Как я пишу некоторый материал, которым удостаивают, чтобы другие классы использовали"

1
ответ дан Alex Wayne 24 November 2019 в 02:40
поделиться

Лично я повышаю NotImplementedError в методах абстрактных классов. Но можно хотеть упустить его из 'нового' метода по причинам, которые Вы упомянули.

4
ответ дан Zack 24 November 2019 в 02:40
поделиться

Какой цели Вы пытаетесь служить с абстрактным классом? Существует, вероятно, лучший способ сделать это в рубине, но Вы не предоставляли подробной информации.

Мой указатель - это; используйте смешивание не наследование.

4
ответ дан jshen 24 November 2019 в 02:40
поделиться

Если Вы хотите пойти с uninstantiable классом в Вашем методе A.new, проверьте если сам == прежде, чем бросить ошибку.

, Но действительно, модуль кажется больше как то, что Вы хотите здесь —, например, Счетный вид вещи, которая могла бы быть абстрактным классом на других языках. Вы технически не можете разделить их на подклассы, но вызов include SomeModule достигает примерно той же цели. Есть ли некоторая причина, это не будет работать на Вас?

4
ответ дан Chuck 24 November 2019 в 02:40
поделиться

За прошлые 6 1/2 лет программирования Ruby я не имею , нуждался абстрактный класс однажды.

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

, Поскольку другие предложили, смешивание более подходит для вещей, которые, как предполагается, являются интерфейсами (поскольку Java определяет их), и пересмотр прежнего мнения Вашего дизайна более подходит для вещей, которые "нуждаются" в абстрактных классах с других языков как C++.

Обновление 2019: Мне haven’t были нужны абстрактные классы в Ruby в 16ВЅ годы использования. Все, что, говорят все люди, комментирующие мой ответ, обращено путем фактического изучения Ruby и использования соответствующих инструментов, как модули (которые даже дают Вам общие реализации). Существуют люди в командах, которыми я управлял, кто создал классы, которые имеют базовое внедрение, которые перестали работать (как абстрактный класс), но это главным образом трата кодирования, потому что NoMethodError привел бы к тому же самому результату как AbstractClassError в производстве.

10
ответ дан Austin Ziegler 24 November 2019 в 02:40
поделиться
class A
  private_class_method :new
end

class B < A
  public_class_method :new
end
14
ответ дан bluehavana 24 November 2019 в 02:40
поделиться

Попробуйте это:

class A
  def initialize
    raise 'Doh! You are trying to instantiate an abstract class!'
  end
end

class B < A
  def initialize
  end
end
43
ответ дан Andrew Peters 24 November 2019 в 02:40
поделиться

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

Языки с утиной типизацией, такие как Ruby, используют наличие/отсутствие или поведение методов во время выполнения, чтобы определить, следует ли их вызывать или нет. Поэтому ваш вопрос, применительно к абстрактному методу, имеет смысл

def get_db_name
   raise 'this method should be overriden and return the db name'
end

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

В своем вопросе вы, по сути, пытаетесь воссоздать ключевое слово abstract из Java, которое является кодовым запахом для того, чтобы сделать Java в Ruby.

111
ответ дан 24 November 2019 в 02:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: