Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在我的继承树的不同类之间共享代码_C# - Fatal编程技术网

C# 在我的继承树的不同类之间共享代码

C# 在我的继承树的不同类之间共享代码,c#,C#,假设我有以下继承树: ______ Object______ / \ Food Material / \ / \ Egg Carrot Box Axe 用C表示# 现在我只想在类框和Egg之间共享功能,例如: bool opened = true; public void Open() { open = tr

假设我有以下继承树:

        ______ Object______
       /                   \
     Food              Material
   /     \            /        \
Egg       Carrot   Box          Axe
用C表示#

现在我只想在类框和Egg之间共享功能,例如:

bool opened = true;

public void Open() { open = true; }
public void Close() { open = false; }
public bool IsOpen() { return opened; }
这是一个简短的例子,但它可能会更长

正确的方法是什么?如果我使用继承,其他类(如Carrot和Axe)将得到它,这是我不希望看到的

更新
许多人提到了作文。有人能在我介绍的示例中向我展示一下它是如何工作的吗?

为什么不使用接口呢<代码>启用IOP

interface IOpenable {
    void Open();
    void Close();
    bool IsOpen();
}

为什么不使用接口呢<代码>启用IOP

interface IOpenable {
    void Open();
    void Close();
    bool IsOpen();
}

您有几个选择:

  • 使用接口
  • 例:

    然后,任何需要可打开/可关闭行为的类都可以相应地实现接口

  • 从实现所需行为的其他对象中选择并组合您的对象

  • 您有几个选择:

  • 使用接口
  • 例:

    然后,任何需要可打开/可关闭行为的类都可以相应地实现接口

  • 从实现所需行为的其他对象中选择并组合您的对象

  • 当我想到
    Egg
    Box
    之间的相似性,它们不是
    Carrot
    Axe
    共享的属性时,我首先想到的是它们包含一些东西

  • Egg
    Box
    内容
    ,可以公开、隐藏、添加、删除等
  • 注意这里的语言-
    Egg
    Box
    内容
    。单词have(或has)表示表示表示另一个对象的
    内容的
    对象应用作合成元素

    鸡蛋是一种食物。一个
    含有
    内容物,即
    蛋黄
    蛋清

    框是
    办公材料的一种类型。
    包含
    内容
    ,这些内容是
    办公用品

    我可以这样写:

    public class Food : Object 
    {
        public void Eat() { }
    }
    
    public class OfficeMaterial : Object { }
    
    public class Contents : Object 
    {
        bool _visible = false;
    
        List<Object> _things = new List<Object>();
    
        public int Count { get { return _things.Count; } }
    
        public bool IsOpen { get { return _visible; } }
    
        public void Expose()
        {
            _visible = true;
        }
    
        public void Hide()
        {
            _visible = false;
        }
    
        public void Add(object thing)
        {
            _things.Add(thing);
        }
    
        public bool Remove(object thing)
        {
            return _things.Remove(thing);
        }
    }
    
    public class Box : OfficeMaterial 
    {
        public Contents BoxContents = new Contents();
    }
    
    public class Egg : Food 
    {
        public Contents EggContents = new Contents();
    }
    

    Eat()
    方法是
    Food
    类的方法。
    Expose()
    方法是
    内容类的方法,而不是
    食品类或
    办公材料类的方法,也不属于
    Egg
    Box
    类。

    当我想到
    Egg
    Box
    之间的相似性时,我首先想到的是它们包含一些东西

  • Egg
    Box
    内容
    ,可以公开、隐藏、添加、删除等
  • 注意这里的语言-
    Egg
    Box
    内容
    。单词have(或has)表示表示表示另一个对象的
    内容的
    对象应用作合成元素

    鸡蛋是一种食物。一个
    含有
    内容物,即
    蛋黄
    蛋清

    框是
    办公材料的一种类型。
    包含
    内容
    ,这些内容是
    办公用品

    我可以这样写:

    public class Food : Object 
    {
        public void Eat() { }
    }
    
    public class OfficeMaterial : Object { }
    
    public class Contents : Object 
    {
        bool _visible = false;
    
        List<Object> _things = new List<Object>();
    
        public int Count { get { return _things.Count; } }
    
        public bool IsOpen { get { return _visible; } }
    
        public void Expose()
        {
            _visible = true;
        }
    
        public void Hide()
        {
            _visible = false;
        }
    
        public void Add(object thing)
        {
            _things.Add(thing);
        }
    
        public bool Remove(object thing)
        {
            return _things.Remove(thing);
        }
    }
    
    public class Box : OfficeMaterial 
    {
        public Contents BoxContents = new Contents();
    }
    
    public class Egg : Food 
    {
        public Contents EggContents = new Contents();
    }
    

    Eat()
    方法是
    Food
    类的方法。
    Expose()
    方法是
    Contents
    类的方法,而不是
    Food
    类或
    OfficeMaterials
    类,也不是
    Egg
    Box
    类的方法。

    这是一种有效的多重继承,C除了通过接口之外不支持

    一个选项是在不使用Open方法的情况下创建一个接口(否则必须实现它,因此这仅用于键入目的),然后在接口旁边的静态类中实现一个静态扩展方法

    public Interface IOpenable { }
    
    public static class IOpenableExtensions {
      public static Open(this IOpenable obj){
          // work on any concrete implementation of IOpenable
      }
    }
    
    用法:

    var box = new Box; // Box implements IOpenable
    var egg = new Egg; // Egg implements IOpenable
    box.Open();
    egg.Open();
    
    当实际继承反映核心结构或组织,而接口提供某些对象共享的公共“行为”时,此模式可能会很好地工作。一个类可以实现一个或多个这样的接口

    C#8默认接口实现可能会使这种模式更加常见

    实际上,在使用处理基类的函数时,通常需要将对象强制转换到接口

    public IEnumerable<Food> GetFoods(){ ... }
    
    public void HandleFood() {
        for(var food in GetFoods()) {
            if(food is IOpenable openableFood){ 
                 openableFood.Open();
            }
        }
    }
    

    这实际上是多重继承,C#除了通过接口之外不支持其他继承

    一个选项是在不使用Open方法的情况下创建一个接口(否则必须实现它,因此这仅用于键入目的),然后在接口旁边的静态类中实现一个静态扩展方法

    public Interface IOpenable { }
    
    public static class IOpenableExtensions {
      public static Open(this IOpenable obj){
          // work on any concrete implementation of IOpenable
      }
    }
    
    用法:

    var box = new Box; // Box implements IOpenable
    var egg = new Egg; // Egg implements IOpenable
    box.Open();
    egg.Open();
    
    当实际继承反映核心结构或组织,而接口提供某些对象共享的公共“行为”时,此模式可能会很好地工作。一个类可以实现一个或多个这样的接口

    C#8默认接口实现可能会使这种模式更加常见

    实际上,在使用处理基类的函数时,通常需要将对象强制转换到接口

    public IEnumerable<Food> GetFoods(){ ... }
    
    public void HandleFood() {
        for(var food in GetFoods()) {
            if(food is IOpenable openableFood){ 
                 openableFood.Open();
            }
        }
    }
    

    这可能与你有关:作文是你的朋友。无论如何,继承被高估了(我个人的观点)。@Dbugger您想要在类之间共享代码,可能需要共享一些行为。组合解决方案是将该行为放入一个类中,然后添加该类的一个实例作为私有membe