代码之家  ›  专栏  ›  技术社区  ›  Nate-Wilkins

如何指定要使用其类型的子类?

  •  0
  • Nate-Wilkins  · 技术社区  · 13 年前

    比方说我有这样一门课:

    public abstract class Foo
    {
        public void Access(Foo foo)
        {
            /*
            if (foo is same type as implemented)
                AccessIfSameImplementation(foo);
            else
                AccessIfDifferentImplementation(foo);
            */
        }
    
        protected abstract void AccessIfSameImplementation(Foo foo);
    
        private void AccessIfDifferentImplementation(Foo foo)
        {
             //do stuff with the different implementations
        }
    }
    

    所以方法 Access 它本身有一种类型,根据定义,它将是一种我们并不真正关心它是什么的实现,只要它继承自 Foo …但我希望此方法检查传入的对象是否与其实现的类型相同。

    就像这样:

    public class Bar : Foo
    {
        protected override void AccessIfSameImplementation(Foo foo)
        {
            // TODO: How do I force foo to always be a Bar
            // do specific Bar stuff
        }
    }
    

    目前我有一个 Name 字段,指示是否传入 foo.Name 与电流相同 名称 除此之外,我还考虑过使用泛型,但再次认为这不是解决这个问题的正确方法。

    编辑:

    关于我正在使用的实际结构的一些背景知识。

    这个 Foo公司 上面定义的类代表创建一组对象的工厂 List<X> objs 这些对象是由实现的属性生成的 Foo公司 对象现在,我有一些其他类比较这些工厂,但我不希望这些工厂因为全部生产而变得臃肿。因此,我不想让工厂膨胀,而是简单地检查它们是否有相同的实现,如果有,则比较抽象比较器定义的属性,否则就会井喷。我稍后有时间会补充更多内容。

    如果有人有更好的头衔,请推荐一个。

    3 回复  |  直到 13 年前
        1
  •  2
  •   Nate-Wilkins    13 年前

    没事,所以我想我就是不能把事情想清楚。所需要做的就是直接在公共方法中进行类型比较 Access

    public void Access(Foo foo)
    {
        if (GetType() == foo.GetType) //Duh...
        {
             AccessIfSameImplementation(foo);
        }
        else
        {
             AccessIfDifferentImplementation(foo);
        }
    }
    
        2
  •  1
  •   jstromwick    13 年前

    我不完全确定你的意图是什么,但你不能在子类中更改抽象方法的签名。有一种想法是,如果你得到了一个不合适的foo,就进行参数检查并抛出一个异常:

    public abstract class Foo
    {
        public void Access(Foo foo)
        {
            if (foo.GetType() == GetType())
            {
                AccessIfSameImplementation(foo);
            }
            else
            {
                AccessIfDifferentImplementation(foo);
            }
        }
    
        protected abstract void AccessIfSameImplementation(Foo foo);
    
        private void AccessIfDifferentImplementation(Foo foo)
        {
            //do stuff with the different implementations
        }
    }
    public class Bar : Foo
    {
        public string Baz { get; set; }
    
        protected override void AccessIfSameImplementation(Foo foo)
        {
            var bar = foo as Bar;
    
            if (bar == null)
            {
                throw new ArgumentException("Argument foo is not of type Bar");
            }
    
            //Do Bar stuff below
            bar.Baz = "Yay!";
        }
    }
    
        3
  •  1
  •   Dan    13 年前

    保持简单。保持抽象类的抽象性,但给出 Access 方法的默认实现 Foo 不可知论者将其保留为子类,以提供使用该子类成员的自定义实现。您还可以使子类可以选择返回基类中实现的默认逻辑:

    public abstract class Foo
    {
        public virtual void Access(Foo foo)
        {
            // perform the default implementation here, but mark as virtual to enable a child class to override it.
        }
    }
    
    public class Bar : Foo
    {
        public override void Access(Foo foo)
        {
            var bar = foo as Bar;
            if (bar != null)
            {
                // If you get here, that means foo is a Bar.
                // Just use bar now and ignore foo.
            }
            else
            {
                // Fall back on the base classes implementation
                base.Access(foo);
            }
        }
    }