روبي استثناء الميراث مع ديناميكيا الطبقات
-
09-06-2019 - |
سؤال
أنا جديدة على روبي, لذا لدي بعض المشاكل في فهم هذا غريب استثناء المشكلة أواجه.أنا باستخدام روبي-aaws جوهرة للوصول إلى الأمازون ECS: http://www.caliban.org/ruby/ruby-aws/.هذا يحدد فئة الأمازون::AWS:خطأ:
module Amazon
module AWS
# All dynamically generated exceptions occur within this namespace.
#
module Error
# An exception generator class.
#
class AWSError
attr_reader :exception
def initialize(xml)
err_class = xml.elements['Code'].text.sub( /^AWS.*\./, '' )
err_msg = xml.elements['Message'].text
unless Amazon::AWS::Error.const_defined?( err_class )
Amazon::AWS::Error.const_set( err_class,
Class.new( StandardError ) )
end
ex_class = Amazon::AWS::Error.const_get( err_class )
@exception = ex_class.new( err_msg )
end
end
end
end
end
هذا يعني أنه إذا كنت الحصول على رمز الخطأ مثل AWS.InvalidParameterValue
, هذا وسوف تنتج (في الاستثناء متغير) فئة جديدة Amazon::AWS::Error::InvalidParameterValue
الذي هو فئة فرعية من StandardError
.
الآن هنا حيث يحصل غريب.لدي بعض التعليمات البرمجية التي تبدو مثل هذا:
begin
do_aws_stuff
rescue Amazon::AWS::Error => error
puts "Got an AWS error"
end
الآن, إذا do_aws_stuff
يلقي NameError
, ، الانقاذ كتلة يحصل تشغيلها.يبدو أن أمازون::AWS::خطأ ليس الفائقة التي تم إنشاؤها خطأ - أعتقد بما انها وحدة كل ما هو فئة فرعية من ذلك ؟ بالتأكيد إذا كنت تفعل:
irb(main):007:0> NameError.new.kind_of?(Amazon::AWS::Error)
=> true
يقول true
, التي لا تجد مربكة ، وخاصة في ضوء هذا:
irb(main):009:0> NameError.new.kind_of?(Amazon::AWS)
=> false
ما يجري و كيف من المفترض أن فصل أوس أخطاء من نوع آخر من الأخطاء ؟ يجب أن أفعل شيئا مثل:
begin
do_aws_stuff
rescue => error
if error.class.to_s =~ /^Amazon::AWS::Error/
puts "Got an AWS error"
else
raise error
end
end
الذي يبدو استثنائية الخربة.الأخطاء طرح ليسوا فئة AWSError إما إنهم أثار مثل هذا:
error = Amazon::AWS::Error::AWSError.new( xml )
raise error.exception
لذا الاستثناءات أبحث عن rescue
من هي ولدت استثناء أنواع فقط ترث من StandardError.
للتوضيح لدي سؤالان:
لماذا NameError, روبي بنيت في الاستثناء ،
kind_of?(Amazon::AWS::Error)
, الذي هو وحدة ؟
الجواب: قلتinclude Amazon::AWS::Error
في الجزء العلوي من الملف ظنا منه أنه نوع من مثل جافا استيراد أو C++ وتشمل.ما هذا فعلا تمت إضافة كل ما هو معرف فيAmazon::AWS::Error
(الحاضر والمستقبل) الضمني نواة الطبقة التي هي سلف من كل فئة.وهذا يعني أي شيء سوف تمرkind_of?(Amazon::AWS::Error)
.وكيف نميز بشكل حيوي إنشاء استثناءات في
Amazon::AWS::Error
من عشوائية استثناءات أخرى من مكان آخر ؟
المحلول
حسنا سأحاول المساعدة هنا :
أول وحدة ليس فئة ، فإنه يسمح لك لخلط السلوك في الصف.الثاني انظر المثال التالي :
module A
module B
module Error
def foobar
puts "foo"
end
end
end
end
class StandardError
include A::B::Error
end
StandardError.new.kind_of?(A::B::Error)
StandardError.new.kind_of?(A::B)
StandardError.included_modules #=> [A::B::Error,Kernel]
kind_of?يقول لك نعم, خطأ لا تمتلك كل من::B::خطأ في السلوك (وهو أمر طبيعي لأنه يتضمن::B::خطأ) أنها لا تشمل كل سلوك من::B وبالتالي ليس من A::B نوع.(بطة في الكتابة)
الآن هناك فرصة جيدة جدا أن روبي-أوس تعيد فتح أحد المتفوقة من NameError ويشمل الأمازون::AWS:خطأ في هناك.(القرد الترقيع)
يمكنك معرفة برمجيا حيث وحدة تدرج في التسلسل الهرمي التالي :
class Class
def has_module?(module_ref)
if self.included_modules.include?(module_ref) and not self.superclass.included_modules.include?(module_ref)
puts self.name+" has module "+ module_ref.name
else
self.superclass.nil? ? false : self.superclass.has_module?(module_ref)
end
end
end
StandardError.has_module?(A::B::Error)
NameError.has_module?(A::B::Error)
بخصوص سؤالك الثاني أنا لا أستطيع رؤية أي شيء أفضل من
begin
#do AWS error prone stuff
rescue Exception => e
if Amazon::AWS::Error.constants.include?(e.class.name)
#awsError
else
whatever
end
end
(تحرير -- البرمجية أعلاه لا يعمل كما هو :اسم يشمل وحدة البادئة وهي ليست حالة من ثوابت الصفائف.يجب عليك بالتأكيد الاتصال lib المشرف على AWSError الطبقة تبدو أكثر مثل مصنع صف لي :/ )
ليس لدي روبي-aws هنا caliban حظر الموقع من قبل الشركة جدار الحماية لذلك لا أستطيع اختبار أبعد من ذلك بكثير.
بشأن ما يلي :قد يكون الشيء به القرد الترقيع على StandardError الهرمي.أنا لست متأكدا بعد الآن ولكن على الأرجح تفعل ذلك في جذر ملف خارج كل السياق بما في ذلك وحدة على الكائن أو الكائن metaclass.(هذا هو ما يمكن أن يحدث في المجلس ، حيث السياق الافتراضي هو كائن غير متأكد حول ملف)
من معول على وحدات :
A couple of points about the include statement before we go on. First, it has nothing to do with files. C programmers use a preprocessor directive called #include to insert the contents of one file into another during compilation. The Ruby include statement simply makes a reference to a named module. If that module is in a separate file, you must use require to drag that file in before using include.
(تحرير -- أنا لا يمكن أن يبدو أن تكون قادرة على التعليق باستخدام هذا المتصفح :/ ياي تخوض في المنصات)
نصائح أخرى
حسنا, من ما أستطيع أن أقول:
Class.new( StandardError )
وخلق طبقة جديدة مع StandardError قاعدة الطبقة ، لذلك لن يكون الأمازون::AWS::خطأ على الإطلاق.هو مجرد المعرفة في الوحدة النمطية الذي هو على الارجح السبب في ذلك هو kind_of?الأمازون::AWS::خطأ.ربما ليس kind_of?الأمازون::AWS لأنه ربما وحدات لا عش لأغراض kind_of??
آسف, أنا لا أعرف وحدات جيدا في روبي ، ولكن بالتأكيد الفئة الأساسية ستكون StandardError.
التحديث:بالمناسبة ، من روبي مستندات:
obj.kind_of?(الطبقة) => true أو false
إرجاع true إذا كان الصف فئة من الكائنات ، أو إذا كان الصف واحدا من superclasses من الكائنات أو وحدات المدرجة في الكائنات.
أردت فقط أن تتناغم في:وأود أن نتفق على أن هذا هو خلل في ليب رمز.ربما أنه ينبغي قراءة:
unless Amazon::AWS::Error.const_defined?( err_class )
kls = Class.new( StandardError )
Amazon::AWS::Error.const_set(err_class, kls)
kls.include Amazon::AWS::Error
end
قضية واحدة كنت تقوم بتشغيل إلى أن Amazon::AWS::Error::AWSError
ليست في الواقع استثناء.عندما raise
ويسمى ، يبدو أن نرى إذا كانت المعلمة الأولى يستجيب exception
طريقة استخدام نتيجة ذلك بدلا من ذلك.أي شيء هو فئة فرعية من Exception
سوف يعود نفسه عندما exception
ويسمى لذلك يمكنك أن تفعل أشياء مثل raise Exception.new("Something is wrong")
.
في هذه الحالة ، AWSError
وقد exception
تعيين سمة القارئ الذي يحدد قيمة على التهيئة إلى شيء من هذا القبيل Amazon::AWS::Error::SOME_ERROR
.وهذا يعني أنه عند استدعاء raise Amazon::AWS::Error::AWSError.new(SOME_XML)
روبي ينتهي الدعوة Amazon::AWS::Error::AWSError.new(SOME_XML).exception
والتي سوف يعود مثيل Amazon::AWS::Error::SOME_ERROR
.وكما أشار أحد المستجيبين ، هذه الفئة مباشرة فرعية من StandardError
بدلا من كونها فرعية مشتركة الأمازون خطأ.حتى يتم تصحيح جان الحل هو على الأرجح أفضل رهان.
اتمنى التي ساعدت على شرح أكثر من ما هو في الواقع يجري وراء الكواليس.