【问题标题】:Isolate dependencies while building object relationships in ruby在 ruby​​ 中建立对象关系时隔离依赖关系
【发布时间】:2017-10-21 07:39:58
【问题描述】:

我第一次通过将我的应用程序域(公立高中)建模为对象来练习 OOP,但我一直坚持如何在不引入大量外部依赖项的情况下创建类之间的关系。

我有很多想要构建的关系,所以为了学习一般原则,我在这里给出了两个类和示例对象来说明我遇到的困难。

我有两个课程GradeTranscriptTranscript 的每个实例都有一个实例变量@mark,现在它是一个字符串。我收集了每个类的所有实例一个grades 哈希和一个transcripts 哈希。

问题:如何修改这些类以使@mark 引用相应的Grade 实例?

(或者,这完全是错误的方法吗?)

Grade 有一个学生可以收到的每个可能的期​​末成绩的实例

class Grade
  attr_accessor :mark, :alpha_equivalent, :numeric_range_low, :numeric_range_high, :numeric_qquivalent, :pass_fail_equivalent, :description

  def initialize(args)
    @mark = args["Mark"]
    @alpha_equivalent = args["AlphaEquivalent"]
    @numeric_range_low = args["NumericRangeLow"]
    @numeric_range_high = args["NumericRangeHigh"]
    @numeric_equivalent = args["NumericEquivalent"]
    @pass_fail_equivalent = args["PassFailEquivalent"]
    @description = args["Description"]
  end
end

来自等级哈希的示例对象:

grades["100"] =>
#<Grade:0x007f9fcb077d68
 @alpha_equivalent="100",
 @description="100 out of 100",
 @mark="100",
 @numeric_equivalent="100",
 @numeric_range_high="100",
 @numeric_range_low="100",
 @pass_fail_equivalent="P">

Transcript 拥有学生所学所有课程的每个期末成绩的实例

class Transcript
    attr_accessor :student_id, :last_name, :first_name, :grade, :official_class, :school, :year, :term, :course, :course_title, :mark, :pass_fail, :credits

    def initialize(args)
        @student_id = args["StudentID"]
        @last_name = args["LastName"]
        @first_name = args["FirstName"]
        @grade = args["Grade"]
        @official_class = args["OffClass"]
        @school = args["school"]
        @year = args["Year"]
        @term = args["Term"]
        @course = args["Course"]
        @course_title = args["Course Title"]
        @mark = args["Mark"]
        @credits = args["Credits"]
        @grade_entry_cohort = args["GEC"]
  end
end

来自成绩单哈希的示例对象:

transcripts["foobar-COURSE1-100"] =>
  #<Transcript:0x007f9fce8786b8
   @course="COURSE1",
   @course_title="Example Course",
   @credits="5",
   @first_name="FOO",
   @grade="100",
   @grade_entry_cohort="V",
   @last_name="BAR",
   @mark="100",
   @official_class="000",
   @school="1",
   @student_id="0123",
   @term="1",
   @year="2000">

我正在实例化 CSV 源文件中的所有对象,然后将它们收集到哈希中,因为我希望能够直接处理它们。

【问题讨论】:

    标签: ruby class oop relationship


    【解决方案1】:

    听起来您需要 Transcript#grade 返回一个 Grade 实例。因此,让我们为此创建一个方法:

    class Grade
      def self.all
        @all ||= {}
      end
    
      def self.find(mark)
        all[mark]
      end
    end
    

    现在,需要填充Grade.all。这可以通过您的 CSV 来实现:

    grade_args = %w[alpha_equivalent description mark numeric_equivalent numeric_range_high numeric_range_low pass_fail_equivalent]
    CSV.parse { |row| Grade.all.merge(csv['mark'] => Grade.new(row.slice(*grade_args)}
    

    现在,我们可以像这样修改Transcript

    class Transcript
      def initialize(args)
        @args = args
      end
    
      def grade
        @grade ||= Grade.find(args['mark'])
      end
    
      private
    
      attr_reader :args
    end
    

    【讨论】:

    • 您提到的||= 运算符听起来非常有用,谢谢!我肯定想使用第二种定义方法的方法,但我面临的挑战是关于等级的属性包含在Grade 类的实例中。当我将args 提供给成绩单时,成绩的值是一个字符串。我需要做的是弄清楚如何编写一个方法,该方法将使用 args 中的字符串在 Grades 哈希中查找正确的实例,其中包含所有 Grade 实例。
    • 基本上是因为我将两个源文件输入到我的程序中,一个包含所有成绩的含义信息,另一个列出学生收到的成绩
    • 已更新以更准确地解决您的问题。
    【解决方案2】:

    假设您之前已经创建了 grades 哈希:

    # read args from csv
    # id built from first, last, course, and grade
    transcripts[id] = Transcript.
      new(args.merge('Mark' => grades[args['Mark']])
    

    它使用Hash#merge 扩展args 并使用之前构建的Grade 实例。

    【讨论】:

    • 所以从你的描述听起来这基本上是查找匹配 id 的记录,然后它是否通过为 mark 实例变量设置一个新值来修改现有实例?当我看到Transcript.new 调用时,它看起来像是在构建一个新实例,但您提到它正在扩展在transcripts 哈希中找到的实例?
    • @zqe 此代码将替换您已经在做的transcripts 大楼。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-11
    • 2011-12-31
    • 2015-12-28
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多