java—私有示例可以在对象之间共享吗?

sdnqo3pr  于 2021-06-30  发布在  Java
关注(0)|答案(7)|浏览(334)

我只允许在我正在学习的编程课程中使用私有成员,我想知道这样的东西是否可以。

public class View {
    private Model object_;
    public View(Model object) {
       object_ = object;
       //blah blah blah
    }
//blah blah blah
}

public class Controller {
    private Model object_;
    public Controller(Model object) {
       object_ = object;
       //blah blah blah
    }
//blah blah blah
}

public class MainClass {
    public static void main(String [ ] args) {
        Model m = new Model();
        Controller c = new Controller(m);
        View v = new View(m);
        //blah blah blah
    }
}

view和controller类都拥有与私有字段相同的模型示例。可以接受吗?这似乎违反了私人领域的概念。我试着问我的教授,他说可以,但我不确定他是否理解我的问题,或者我是否理解他的答案:)

b4qexyjb

b4qexyjb1#

关于标题问题:是的,没关系。想象一棵树,其中兄弟姐妹共享对父级的引用。这种情况很常见。

gpfsuwkq

gpfsuwkq2#

据我所知,没有硬性的“私人领域法则”说一个物体可以被多个阶级私下持有。对于不可变引用类之类的对象,多个类示例可以接收不可变引用类并将其作为私有属性保存是有意义的。
在您的示例中,carl是对的——视图和控制器通常应该在某些方法中将模型作为参数,而不是保留对它们的引用。所以代码看起来更像这样:

public Response handleRequest(Request request) {
    Controller c = new Controller();
    Model m = c.processRequest(request);
    View v = new View();
    Response response = v.createResponse(model);
    return response;
}
unhi4e5o

unhi4e5o3#

简单的回答是它很好。
较长的答案(暂时忘记mvc,因为mvc似乎是一个这样做的例子,而不是问题的核心)是您必须考虑可变性。如果一个对象是不可变的(对象上的任何字段都不能更改),那么共享是一件非常好的事情,它可以减少内存占用,并且没有真正的缺点。
但是,如果对象是可变的,那么您必须了解更改对象的状态如何影响引用它的对象。在mvc中,很典型的情况是看到模型发生了变化,然后让视图最终在此基础上进行了调整,因此您可以将其构建到设计中,但请考虑以下情况:

private Collection myCollection; 

  public void setMyCollection(Collection someCollection) { 
       myCollection = someCollection; 
  }

这样的代码必须非常有信心,调用方不会向它传递一个可变的集合,该集合随后会发生更改,否则它必须允许这样做。解决上述问题的典型方法是复制一份( myCollection = new ArrayList(someCollection); )
总之,这是一种常见的做法,但当对象是可变的时,您必须仔细考虑对设计的影响。

w1jd8yoj

w1jd8yoj4#

是的,这是可以接受的,私有字段应该用来强制封装,如果需要的话,可以通过getter/setter方法控制对这些字段的访问。如果这些字段是公共的,甚至是打包的,那么外部类可能开始依赖于类的实现,这会在重构方法等方面限制您。允许其他类访问它们应该访问的字段可能会导致隐私泄露。
如果模型是公共的。
班级混乱{
模型amodel=对象;amodel.dowhathehelliwanttoyourmodel();
}
这可能会完全改变你的系统状态。

vd2z7a6w

vd2z7a6w5#

可以接受吗?
是的。
这似乎违反了私人领域的概念
没有。控制器无法从视图中更改示例,因为它是私有的。
请考虑尝试更改视图中模型的以下代码行:

public class Controller {
    private Model object_;
    public Controller(Model object) {
        object_ = object;
        this.object_.view.object_ = new Model(); // doesn't work.
        // or view.object_ = ....            
       //blah blah blah
    }
    //blah blah blah
}

这是行不通的,第一,模型没有视图的引用,第二,如果模型有视图的引用,那么 controller 无法更改 model 因为他看不见。
在某些情况下,共享同一个对象可能是不可取的。例如,如果依赖给定对象的状态,而该状态被其他对象更改,则代码可能会失败。请参阅防御性复制,这就是为什么建议使用不可变对象并限制对其的访问。
但特别是在mvc设计模式中,共享一个正是您所需要的对象,或者至少共享该对象的状态。在mvc中,您需要的是 View 以及 Controller 意识到 Model 州。看到同一个对象并不会降低它们的私密性(即每个对象都不知道它们看到的是同一个对象),这允许低耦合
肯定会破坏对象隐私的东西将具有以下非隐私属性:

class View {
   public Model m; 
}
class Controller {
    public Model m;  
}
....
public static void main( String ... args ) { 
     Model m = ... 
     View v = new View();
     Controller c = new Controller();
     v.m = m;
     c.m = m;
}

因为不会有任何访问控制来防止发生大的变化。

sgtfey8w

sgtfey8w6#

如果您阅读本文,您将看到理想情况下控制器位于模型和视图之间。因此,我可能会稍微重新组织您的依赖关系(对此有一些不同意见-见下文)
但是你的问题的答案(不管是哪个域)是,你可以共享这些私人引用。理想情况下,它们应该是对接口的引用,实现可以在不更改依赖类的情况下进行更改。所以(例如)你会有一个 Model 接口和实现 ModelImpl ,共享引用的类型为 Model . 然后可以在以后替换不同的实现,而不会影响大部分代码。

5cnsuln7

5cnsuln77#

简而言之:两个不同的类没有任何问题,它们的私有成员变量引用同一个对象。这很常见。
长话短说:我猜你的教授可能在这里说的是: private Model object_ 是对象引用变量(不是基元)。所以当你经过的时候 object_ 在controller和view的构造函数中,传递一个指向 object_ ,而不是传递 object_ .
是否选择在controller和view中将它们存储为private是一个完全不同的决定。我熟悉禁止使用非私有成员变量的大学编程课程。他们想引入一些面向对象的概念,比如封装(稍后),然后他们会告诉您为私有成员变量创建公共访问器和变异器。这通常是一个很好的开始原则,因为只有当您有充分的理由这样做时,才应该使用受保护和公共成员变量。
是的,这些都是正确的java,但是这是否真的是你想用你的代码做的是另一回事(见caleb的答案)。

相关问题