如何通过“实际”类找到实例变量?

时间:2017-12-26 17:50:47

标签: class oop crystal-lang

我正在编写的程序是将元素存储在grid类型Position => LivingBeing | Thing的哈希中。此grid存储在Map上,我希望此Map返回类Apple元素的位置,该类是Thing的子类。

但是,当使用typeof()获取课程时,我会获得LivingBeing | Thing而不是子类Apple

以下是Map类:

class Map
  @@grid = {} of Position => LivingBeing | Thing

  def initialize()
  end

  # Add an entity to the grid
  def add_entity(new_entity : LivingBeing | Thing)
    @@grid[new_entity.position] = new_entity
  end

  # Return the position of an object of class "something"
  def self.where_is?(something : Class)
    # First attempt was to get the key by the value
    # @@grid.key(something)

    @@grid.each do |position, thing|
      # Returns "thing #<Apple:0x55f1772085c0> at Position(@x=1, @y=2) is (LivingBeing | Thing)"
      puts "thing #{thing} at #{position} is #{typeof(thing)}"
      position if typeof(thing) == something
    end
  end

这里是Thing类:

abstract class Thing
  getter position
  @name = "Unkown object"

  def initialize(@position : Position)
  end
end

class Apple < Thing
  @name = "Apple"
end

这里是Position结构:

struct Position
  getter x, y

  def initialize(@x : Int32, @y : Int32)
  end
end

这是我尝试通过的测试:

it "gives a random thing location based on its class" do
  world = Map.new()
  apple = Apple.new(Position.new(1, 2))
  puts "Apple type : #{typeof(apple)}" # Returns "Apple type : Apple"
  world.add_entity(apple)
  position = Map.where_is?(Apple)
  position.should eq Position.new(1, 2)
end

是否有某些类方法或函数可以提供Apple类? 或者这是一个设计问题?

感谢您的回答!

3 个答案:

答案 0 :(得分:1)

我的一个解决方案就是我的功能:

  # Return the position of an object of class "something"
  def self.where_is?(something)
    @@grid.each do |position, thing|
      return position if thing.is_a?(typeof(something))
    end
  end

这是为了测试:

  it "gives a random thing location" do
    world = Map.new(4)
    apple = Apple.new(Position.new(1, 2))
    world.add_entity(apple)
    position = Map.where_is?(Apple.new(Position.new(0, 0)))
    position.should eq Position.new(1, 2)
  end

如果没有其他解决方案,我会像这样使用它。但我希望能够直接搜索课程Apple,而不是创建Apple的实例

我希望能够position = Map.where_is?(Apple)代替。{ position = Map.where_is?(Apple.new(Position.new(0, 0)))

答案 1 :(得分:1)

您可以使用forall来解决此问题:

  # Return the position of an object of class "something"
  def self.where_is?(something : T.class) forall T
    @@grid.each do |position, thing|
      return position if thing.is_a?(T)
    end
  end

并按照您的意愿使用Map.where_is? Apple进行调用。

这是有效的,因为类型变量T(使用forall T引入)可以推断为Apple传递与{{1}匹配的常量Apple类型限制。 T.class是您可以与T一起使用的常量。

答案 2 :(得分:0)

正如@ RX14所说,看起来你想检查运行时“类型”,即.class。这是一个例子:

class Apple
  @name = "Apple"
end

def check(obj : Object)
  obj.class == Apple
end

a=Apple.new
p check(a)